home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 20.ddi / DOCVIEW.PAK / DUMPVIEW.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  13.3 KB  |  535 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1993 by Borland International
  3. //   Implements class TDumpView
  4. //----------------------------------------------------------------------------
  5. #include <owl\owlpch.h>
  6. #include <owl\docmanag.h>
  7. #include <owl\filedoc.h>
  8. #include <owl\listbox.h>
  9. #include <owl\inputdia.h>
  10. #include <owl\dc.h>
  11. #include "dumpview.rc"
  12.  
  13. struct TDumpData;
  14.  
  15. class _DOCVIEWCLASS TDumpView : public TListBox, public TView {
  16.   public:
  17.     TDumpView(TDocument& doc, TWindow* parent = 0);
  18.    ~TDumpView();
  19.     static LPCSTR StaticName() {return "Dump View";}  // put in resource
  20.  
  21.     //
  22.     // overridden virtuals from TView
  23.     //
  24.     LPCSTR   GetViewName(){return StaticName();}
  25.     TWindow* GetWindow()  {return (TWindow*)this;}
  26.     BOOL     SetDocTitle(LPCSTR docname, int index)
  27.                           {return TListBox::SetDocTitle(docname, index); }
  28.     //
  29.     // overridden virtuals from TWindow
  30.     //
  31.     BOOL     Create();
  32.     BOOL     CanClose()   {return TListBox::CanClose() && Doc->CanClose();}
  33.     int    MaxWidth;    // maximum horizontal extent
  34.  
  35.   protected:
  36.     long Origin;
  37.     long FileSize;
  38.     int  UpdateMode; // 0=NotEditing, 1=HighNibble, 2=LowNibble, -1=Flushing
  39.     int  CharWidth;
  40.     int  CharHeight;
  41.     int  EditByte;
  42.     int  EditLine;
  43.     TDumpData* Changes;
  44.     void Init();
  45.     BOOL LoadData(int top, int sel);
  46.     void FormatLine(int index, TDumpData* data);
  47.     BOOL NewEditLine(int line, int byte);
  48.     void EndEditLine();
  49.     void KillChanges();
  50.         
  51.   private:
  52.     //
  53.     // message response functions
  54.     //
  55.     BOOL VnCommit(BOOL force);
  56.     BOOL VnRevert(BOOL clear);
  57.     BOOL VnIsWindow(HWND hWnd) {return HWindow == hWnd;}
  58.     BOOL VnIsDirty();
  59.     BOOL VnDocClosed(int omode);
  60.     void CmEditUndo();
  61.     void CmEditItem();
  62.     void EvPaint();
  63.     void EvKeyDown(UINT key, UINT repeatCount, UINT flags);
  64.     void EvLButtonDown(UINT modKeys, TPoint& point);
  65.     void EvLButtonDblClk(UINT modKeys, TPoint& point);
  66.     void CmSelChange(){} // to prevent interpreting as unprocessed accelerator
  67.  
  68.   DECLARE_RESPONSE_TABLE(TDumpView);
  69.   DECLARE_STREAMABLE(,TDumpView,1);
  70. };
  71.  
  72. DIAG_DECLARE_GROUP(OwlDocView);        // General Doc/View diagnostic group
  73.  
  74. const int DisplayLines = 16;   // initial list box size
  75. const int ListBoxMax = 100;    // max number of lines stored in list box
  76. const int DataWidth = 8;       // number of data bytes per line
  77. const int AddrWidth = 2;       // number of bytes in address
  78. const int LineWidth = AddrWidth*2 + 1 + DataWidth*3 + DataWidth;
  79.  
  80. struct TDumpData {
  81.    long       Addr;
  82.    char       Old[DataWidth];
  83.    char       New[DataWidth];
  84.    int        Count;
  85.    TDumpData* Next;
  86. };
  87.  
  88. DEFINE_RESPONSE_TABLE1(TDumpView, TListBox)
  89.   EV_WM_KEYDOWN,
  90.   EV_COMMAND(CM_DUMPUNDO,    CmEditUndo),
  91.   EV_COMMAND(CM_DUMPEDIT,    CmEditItem),
  92.   EV_WM_PAINT,
  93.   EV_WM_LBUTTONDOWN,
  94.   EV_WM_LBUTTONDBLCLK,
  95.   EV_VN_DOCCLOSED,
  96.   EV_VN_ISWINDOW,
  97.   EV_VN_ISDIRTY,
  98.   EV_VN_COMMIT,
  99.   EV_VN_REVERT,
  100.   EV_NOTIFY_AT_CHILD(LBN_SELCHANGE, CmSelChange),
  101. END_RESPONSE_TABLE;
  102.  
  103. TDumpView::TDumpView(TDocument& doc, TWindow* parent)
  104.          : TView(doc), TListBox(parent, GetNextViewId(), 0,0,0,0)
  105. {
  106.   Init();
  107.   Attr.Style &= ~(WS_BORDER | LBS_SORT);
  108.   Attr.Style |= (LBS_DISABLENOSCROLL);
  109.   Attr.AccelTable = IDA_DUMPVIEW;
  110.   SetViewMenu(new TMenuDescr(IDM_DUMPVIEW,0,1,0,0,0,1));
  111. }
  112.  
  113. void
  114. TDumpView::Init()
  115. {
  116.   Origin = 0;
  117.   UpdateMode = 0;
  118.   Changes = 0;
  119. }
  120.  
  121. BOOL
  122. TDumpView::VnDocClosed(int omode)
  123. {
  124.   int top;
  125.   int sel;
  126.   if (UpdateMode == -1 || !(omode & ofWrite))  // make sure someone else's write
  127.     return FALSE;
  128.   top = GetTopIndex();
  129.   sel = GetSelIndex();
  130.   ClearList();
  131.   LoadData(top, sel);
  132.   return TRUE;
  133. }
  134.  
  135. static char HexDigit(int i)
  136. {
  137.   char c = char((i & 15) + '0');
  138.   if (c > '9')
  139.     c += char('A' - ('9' + 1));
  140.   return c;
  141. }
  142.  
  143. void
  144. TDumpView::FormatLine(int line, TDumpData* data)
  145. {
  146.   char buf[LineWidth + 2];
  147.   int index;
  148.   char* pbuf;
  149.   char* pasc;
  150.   unsigned char chr;
  151.   long addr = data->Addr;
  152.  
  153.   for (index = AddrWidth*2; --index >= 0; addr >>= 4)
  154.     buf[index] = HexDigit((int)addr);
  155.   pbuf = buf + AddrWidth*2;
  156.   *pbuf++ = ' ';
  157.   pasc = pbuf + DataWidth*3;
  158.   for (index = 0; index < DataWidth; index++) {
  159.     if (index < data->Count) {
  160.       chr = data->New[index];
  161.       *pbuf++ = HexDigit(chr >> 4);
  162.       *pbuf++ = HexDigit(chr);
  163.       pasc[index] = char((chr >= 0x20 && chr < 0x7F) ? chr : 0x7F);
  164.     } else {
  165.       *pbuf++ = ' ';
  166.       *pbuf++ = ' ';
  167.       pasc[index] = ' ';
  168.     }
  169.     *pbuf++ = ' ';
  170.   }
  171.   pasc[DataWidth] = 0;  // null terminate buffer
  172.   InsertString(buf, line);
  173. }
  174.  
  175. static long GetAddr(int index)
  176. {
  177.    return index * DataWidth;
  178.    // need to add origin!
  179. }
  180.  
  181. static int GetIndex(long addr)
  182. {
  183.    return int(addr / DataWidth);
  184.    // need to subtract origin!
  185. }
  186.  
  187. BOOL
  188. TDumpView::LoadData(int top, int sel)
  189. {
  190.   TDumpData data;
  191.   istream* inStream;
  192.   int count;
  193.  
  194.   if ((inStream = Doc->InStream(ofRead | ofBinary)) == 0)
  195.     return FALSE;
  196.  
  197.   for (count=0, data.Addr=0; count<ListBoxMax; count++,data.Addr+=DataWidth) {
  198.     inStream->read(data.New, DataWidth);
  199.     if ((data.Count = inStream->gcount()) == 0)
  200.       break;
  201.     FormatLine(-1, &data);
  202.     if (data.Count != DataWidth)
  203.       break;
  204.   }
  205.   SetTopIndex(top);
  206.   SetSelIndex(sel);
  207.   delete inStream;   // close file in case process switch
  208.   return TRUE;
  209. }
  210.  
  211. BOOL
  212. TDumpView::Create()
  213. {
  214.   TRect rect;
  215.   LOGFONT fontinfo;
  216.   HGDIOBJ font = GetStockObject(SYSTEM_FIXED_FONT);
  217.   TListBox::Create();   // throws exception TXInvalidWindow
  218.   SendMessage(WM_SETFONT, (UINT)font, 0L);
  219.   GetObject(font, sizeof(LOGFONT), &fontinfo);
  220.   CharWidth  = fontinfo.lfWidth;
  221.   CharHeight = fontinfo.lfHeight;
  222.   GetClientRect(rect);   // created with 0,0 size, .right is -scroll bar size
  223.   if (rect.right < 0) {  // if new view, else streaming in presized window
  224.     rect.right = LineWidth * CharWidth + (-rect.right+2) + CharWidth/2;
  225.     rect.bottom = CharHeight * DisplayLines;
  226.     MoveWindow(rect);
  227.   //if (!Parent->IsFlagSet(wfMainWindow))// prevent parent shrink if main window
  228.       Parent->SetFlag(wfShrinkToClient);
  229.   }
  230.   if (Doc->GetDocPath() == 0) {  
  231.     return TRUE;           // new file, no data to display
  232.   }
  233.   if (!LoadData(0, 0))
  234.     NotOK();
  235.   return TRUE;
  236. }
  237.  
  238. BOOL
  239. TDumpView::VnCommit(BOOL /*force*/)
  240. {
  241.   TDumpData* edit;
  242.   ostream* outStream;
  243.  
  244.   EndEditLine();
  245.   if (!Changes)
  246.     return TRUE;
  247.   if ((outStream = Doc->OutStream(ofReadWrite | ofBinary)) == 0)
  248.     return FALSE;
  249.   while ((edit = Changes) != 0) {
  250.     outStream->seekp(edit->Addr);
  251.     outStream->write(edit->New, edit->Count);
  252.     // test goodbit
  253.     Changes = Changes->Next;
  254.     delete edit;
  255.   }
  256.   UpdateMode = -1;         // to detect our own close notification
  257.   outStream->seekp(0,ios::end);
  258.   delete outStream;
  259.   return TRUE;
  260. }
  261.  
  262. BOOL
  263. TDumpView::VnRevert(BOOL clear)
  264. {
  265.   EndEditLine();
  266.   KillChanges();
  267.   ClearList();
  268.   return (!clear && Doc->GetDocPath() != 0) ? LoadData(0, 0) : TRUE;
  269. }
  270.  
  271. TDumpView::~TDumpView()
  272. {
  273.   KillChanges();
  274. }
  275.  
  276. BOOL
  277. TDumpView::NewEditLine(int line, int byte)
  278. {
  279.   istream* inStream;
  280.   TDumpData* edit;
  281.   TRect rect;
  282.   BOOL stat = TRUE;
  283.   if (line < 0)
  284.     return FALSE;
  285.   SetSelIndex(line);  // restore index in case changes
  286.   if (UpdateMode > 0) {
  287.     return FALSE;
  288.   }
  289.   if ((inStream = Doc->InStream(ofRead | ofBinary)) == 0)
  290.     return FALSE;
  291.   if ((edit = new TDumpData) == 0)
  292.     return FALSE;
  293.   edit->Addr = GetAddr(line);
  294.   inStream->seekg(edit->Addr);
  295.   // test goodbit
  296.   inStream->read(edit->Old, DataWidth);
  297.   if ((edit->Count = inStream->gcount()) > 0) {
  298.     memcpy(edit->New, edit->Old, edit->Count);
  299.     UpdateMode = 1;
  300.     GetItemRect(line, rect);
  301.     InvalidateRect(rect);
  302.     edit->Next = Changes;
  303.     Changes = edit;
  304.     while (byte >= edit->Count)
  305.       byte--;
  306.     EditByte = byte;
  307.     EditLine = line;
  308.   } else {
  309.     delete edit;
  310.     stat = FALSE;
  311.   }
  312.   delete inStream;
  313.   return stat;
  314. }
  315.  
  316. BOOL
  317. TDumpView::VnIsDirty()
  318. {
  319.   return (Changes
  320.           && (Changes->Next
  321.               || memcmp(Changes->New, Changes->Old, Changes->Count) != 0));
  322. }
  323.  
  324. void
  325. TDumpView::EndEditLine()
  326. {
  327.   TDumpData* edit = Changes;
  328.   if (UpdateMode > 0) {
  329.     TRect rect;
  330.     GetItemRect(EditLine, rect);
  331.     InvalidateRect(rect);
  332.     if (memcmp(edit->New, edit->Old, edit->Count) == 0) {
  333.       Changes = Changes->Next;
  334.       delete edit;
  335.     }
  336.   }
  337.   UpdateMode = 0;
  338. }
  339.  
  340. void
  341. TDumpView::KillChanges()
  342. {
  343.   TDumpData* edit;
  344.   while ((edit = Changes) != 0) {
  345.     Changes = Changes->Next;
  346.     delete edit;
  347.   }
  348. }
  349.  
  350. void
  351. TDumpView::EvLButtonDown(UINT modKeys, TPoint& point)
  352. {
  353.   if (UpdateMode > 0) {
  354.     int index = ((point.x*2 - CharWidth)/(CharWidth*2) - AddrWidth*2)/3;
  355.     if (index >= 0 && index < Changes->Count) {
  356.       EditByte = index;
  357.       UpdateMode = 1;
  358.       TRect rect;
  359.       GetItemRect(EditLine, rect);
  360.       InvalidateRect(rect);
  361.     }
  362.   } else {
  363.     TListBox::EvLButtonDown(modKeys, point);
  364.   }
  365. }
  366.  
  367. void
  368. TDumpView::EvLButtonDblClk(UINT /*modKeys*/, TPoint& point)
  369. {
  370.   int index = ((point.x*2 - CharWidth)/(CharWidth*2) - AddrWidth*2)/3;
  371.   if (index < 0 || index >= DataWidth)
  372.     index = 0;
  373.   int line = point.y/CharHeight + GetTopIndex();
  374.   if (UpdateMode <= 0 || line != EditLine) {
  375.     EndEditLine();
  376.     NewEditLine(line, index);
  377.   }
  378. }
  379.  
  380. void
  381. TDumpView::EvKeyDown(UINT key, UINT repeatCount, UINT flags)
  382. {
  383.   char oldchr, newchr;
  384.   MSG msg;
  385.  
  386.   if (UpdateMode <= 0) {
  387.     if (key != VK_LEFT && key != VK_RIGHT)
  388.       TListBox::EvKeyDown(key, repeatCount, flags);
  389.     return;
  390.   }
  391.   switch (key) {
  392.     case VK_ESCAPE:  // abort changes to current line
  393.       CmEditUndo();
  394.       return;
  395.  
  396.     case VK_RETURN:  // enter changes for current line, not committed yet
  397.       EndEditLine();
  398.       break;
  399.  
  400.     case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
  401.       key += ('0' + 10) - 'A';  // fall through to digit cases
  402.     case '0': case '1': case '2': case '3': case '4':
  403.     case '5': case '6': case '7': case '8': case '9':
  404.       newchr = char(key - '0');
  405.       oldchr = Changes->New[EditByte];
  406.       ::PeekMessage(&msg, HWindow, WM_CHAR, WM_CHAR, PM_REMOVE);
  407.       switch(UpdateMode) {
  408.         case 1:
  409.           newchr = char((oldchr & 0x0F) + (newchr<<4));
  410.           break;
  411.         case 2:
  412.           newchr = char((oldchr & 0xF0) + newchr);
  413.           break;
  414.         default:
  415.           return;
  416.       } 
  417.       Changes->New[EditByte] = newchr;
  418.       DeleteString(EditLine);
  419.       FormatLine(EditLine, Changes);
  420.       SetSelIndex(EditLine);
  421.       if (UpdateMode++ == 2 && EditByte < Changes->Count-1) {
  422.         EditByte++;
  423.         UpdateMode = 1;
  424.       }
  425.       break;
  426.     case VK_UP:  
  427.     case VK_DOWN:
  428.     case VK_PRIOR:
  429.     case VK_NEXT:
  430.     case VK_END:
  431.     case VK_HOME:
  432.       if (UpdateMode > 0)
  433.         return;       
  434.       break;
  435.     case VK_LEFT:
  436.       if (UpdateMode <= 0 || EditByte == 0)
  437.         return;       
  438.       UpdateMode = 1;
  439.       EditByte--;
  440.       break;
  441.     case VK_RIGHT:
  442.       if (UpdateMode <= 0 || EditByte >= (Changes->Count-1))
  443.         return;
  444.       UpdateMode = 1;
  445.       EditByte++;
  446.       break;
  447.     default:
  448.       break;
  449.   }
  450.   TRect rect;
  451.   GetItemRect(EditLine, rect);
  452.   InvalidateRect(rect);
  453. }
  454.  
  455. void
  456. TDumpView::EvPaint()
  457. {
  458.   TRegion updateRgn;
  459.   GetUpdateRgn(updateRgn);
  460.   DefaultProcessing();  // predefined class, don't call TWindow
  461. //TWindow::EvPaint();
  462.   if (UpdateMode <= 0)
  463.     return;
  464.   if (GetSelIndex() != EditLine) { /*::MessageBeep(MB_ICONEXCLAMATION);*/ return;}
  465.   if (GetTopIndex() > EditLine || (GetTopIndex()+DisplayLines) <= EditLine)
  466.     return;
  467.   TRect rect;
  468.   GetItemRect(EditLine, rect);
  469.   rect.left += CharWidth * (AddrWidth*2+1+EditByte*3) + 1;
  470.   rect.right = rect.left + CharWidth * 2;
  471.   // should check if in update region!
  472.   TClientDC dc(HWindow);
  473.   dc.SelectClipRgn(updateRgn);
  474.   dc.IntersectClipRect(rect);
  475. //GetUpdateRgn(updateRgn);
  476.   dc.InvertRgn(updateRgn);
  477. }
  478.  
  479. void
  480. TDumpView::CmEditUndo()
  481. {
  482.   TRect rect;
  483.   TDumpData* edit;
  484.  
  485.   UpdateMode = 0;
  486.   if (!Changes)
  487.     return;
  488.   int index = GetIndex(Changes->Addr);
  489.   DeleteString(index);
  490.   memcpy(Changes->New, Changes->Old, Changes->Count);
  491.   FormatLine(index, Changes);
  492.   SetSelIndex(index);
  493.   edit = Changes;
  494.   Changes = Changes->Next;
  495.   delete edit;
  496.   GetItemRect(index, rect);
  497.   InvalidateRect(rect);
  498. }
  499.  
  500. void
  501. TDumpView::CmEditItem()
  502. {
  503.   int line = GetSelIndex();
  504.   if (UpdateMode > 0) {
  505.     if (line == EditLine)
  506.       return;
  507.     EndEditLine();
  508.   }
  509.   NewEditLine(line, 0);
  510. }
  511.  
  512. IMPLEMENT_STREAMABLE2(TDumpView, TListBox, TView);
  513.  
  514. void*
  515. TDumpView::Streamer::Read(ipstream& is, uint32 /*version*/) const
  516. {
  517.   ReadBaseObject((TListBox*)GetObject(), is);
  518.   ReadBaseObject((TView*)GetObject(), is);
  519.   is >> GetObject()->Origin;
  520.   GetObject()->Init();
  521.   return GetObject();
  522. }
  523.  
  524. void
  525. TDumpView::Streamer::Write(opstream &os) const
  526. {
  527.   WriteBaseObject((TListBox*)GetObject(), os);
  528.   WriteBaseObject((TView*)GetObject(), os);
  529.   os << GetObject()->Origin;
  530. }
  531.  
  532. DEFINE_DOC_TEMPLATE_CLASS(TFileDocument, TDumpView, DumpTemplate);
  533. DumpTemplate dumpTpl("DumpView, Binary files", "*.obj;*.res", 0, 0,
  534.                      dtAutoDelete | dtUpdateDir);
  535.