home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / step13.pak / STEP13DV.CPP < prev    next >
C/C++ Source or Header  |  1997-07-23  |  19KB  |  858 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1994 by Borland International
  3. //   Tutorial application -- step13dv.cpp
  4. //----------------------------------------------------------------------------
  5. #include <owl/owlpch.h>
  6. #include <owl/dc.h>
  7. #include <owl/inputdia.h>
  8. #include <owl/chooseco.h>
  9. #include <owl/gdiobjec.h>
  10. #include <owl/docmanag.h>
  11. #include <owl/filedoc.h>
  12. #include <owl/listbox.h>
  13. #include <classlib/arrays.h>
  14. #include "step13dv.rc"
  15.  
  16. typedef TArray<TPoint> TPoints;
  17. typedef TArrayIterator<TPoint> TPointsIterator;
  18.  
  19. class TLine : public TPoints {
  20.   public:
  21.     // Constructor to allow construction from a color and a pen size.
  22.     // Also serves as default constructor.
  23.     TLine(const TColor& color = TColor(0), int penSize = 1) :
  24.       TPoints(10, 0, 10), PenSize(penSize), Color(color) {}
  25.  
  26.     // Functions to modify and query pen attributes.
  27.     int QueryPenSize() const
  28.     {
  29.       return PenSize;
  30.     }
  31.     const TColor& QueryColor() const
  32.     {
  33.       return Color;
  34.     }
  35.     void SetPen(TColor& newColor, int penSize = 0);
  36.     void SetPen(int penSize);
  37.     friend bool GetPenSize(TWindow* parent, TLine&);
  38.     friend bool GetPenColor(TWindow* parent, TLine&);
  39.  
  40.     // TLine draws itself.  Returns true if everything went OK.
  41.     virtual bool Draw(TDC&) const;
  42.  
  43.     // The == operator must be defined for the container class, even if unused
  44.     bool operator ==(const TLine& other) const
  45.     {
  46.       return &other == this;
  47.     }
  48.     friend ostream& operator <<(ostream& os, const TLine& line);
  49.     friend istream& operator >>(istream& is, TLine& line);
  50.  
  51.   protected:
  52.     int PenSize;
  53.     TColor Color;
  54. };
  55.  
  56. typedef TArray<TLine> TLines;
  57. typedef TArrayIterator<TLine> TLinesIterator;
  58.  
  59. class _USERCLASS TDrawDocument : public TFileDocument {
  60.   public:
  61.     enum {
  62.       PrevProperty = TFileDocument::NextProperty-1,
  63.       LineCount,
  64.       Description,
  65.       NextProperty,
  66.     };
  67.  
  68.     enum {
  69.       UndoNone,
  70.       UndoDelete,
  71.       UndoAppend,
  72.       UndoModify
  73.     };
  74.  
  75.     TDrawDocument(TDocument* parent = 0) :
  76.       TFileDocument(parent), Lines(0), UndoLine(0), UndoState(UndoNone) {}
  77.    ~TDrawDocument()
  78.     {
  79.       delete Lines;
  80.       delete UndoLine;
  81.     }
  82.  
  83.     // implement virtual methods of TDocument
  84.     bool   Open(int mode, const char far* path=0);
  85.     bool   Close();
  86.     bool   IsOpen()
  87.     {
  88.       return Lines != 0;
  89.     }
  90.  
  91.     bool   Commit(bool force = false);
  92.     bool   Revert(bool clear = false);
  93.  
  94.     int    FindProperty(const char far* name);  // return index
  95.     int    PropertyFlags(int index);
  96.     const char* PropertyName(int index);
  97.     int    PropertyCount()
  98.     {
  99.       return NextProperty - 1;
  100.     }
  101.  
  102.     int    GetProperty(int index, void far* dest, int textlen=0);
  103.  
  104.     // data access functions
  105.     const TLine* GetLine(unsigned int index);
  106.     int    AddLine(TLine& line);
  107.     void   DeleteLine(unsigned int index);
  108.     void   ModifyLine(TLine& line, unsigned int index);
  109.     void   Clear();
  110.     void   Undo();
  111.  
  112.   protected:
  113.     TLines* Lines;
  114.     TLine* UndoLine;
  115.     int    UndoState;
  116.     int    UndoIndex;
  117.     string FileInfo;
  118. };
  119.  
  120. class _USERCLASS TDrawView : public TWindowView {
  121.   public:
  122.     TDrawView(TDrawDocument& doc, TWindow* parent = 0);
  123.    ~TDrawView()
  124.     {
  125.       delete DragDC;
  126.       delete Line;
  127.     }
  128.  
  129.     static const char far* StaticName()
  130.     {
  131.       return "Draw View";
  132.     }
  133.  
  134.     const char far* GetViewName()
  135.     {
  136.       return StaticName();
  137.     }
  138.  
  139.   protected:
  140.     TDrawDocument* DrawDoc;  // same as Doc member, but cast to derived class
  141.     TDC* DragDC;
  142.     TPen* Pen;
  143.     TLine* Line; // To hold a single line sent or received from document
  144.  
  145.     // Message response functions
  146.     void EvLButtonDown(uint, TPoint&);
  147.     void EvRButtonDown(uint, TPoint&);
  148.     void EvMouseMove(uint, TPoint&);
  149.     void EvLButtonUp(uint, TPoint&);
  150.     void Paint(TDC&, bool, TRect&);
  151.     void CmPenSize();
  152.     void CmPenColor();
  153.     void CmClear();
  154.     void CmUndo();
  155.  
  156.     // Document notifications
  157.     bool VnCommit(bool force);
  158.     bool VnRevert(bool clear);
  159.     bool VnAppend(unsigned int index);
  160.     bool VnDelete(unsigned int index);
  161.     bool VnModify(unsigned int index);
  162.  
  163.     DECLARE_RESPONSE_TABLE(TDrawView);
  164. };
  165.  
  166. class _USERCLASS TDrawListView : public TListBox, public TView {
  167.   public:
  168.     TDrawListView(TDrawDocument& doc, TWindow* parent = 0);
  169.    ~TDrawListView(){}
  170.     static const char far* StaticName()
  171.     {
  172.       return "DrawList View";
  173.     }
  174.  
  175.     int CurIndex;
  176.  
  177.     // Overridden virtuals from TView
  178.     //
  179.     const char far* GetViewName()
  180.     {
  181.       return StaticName();
  182.     }
  183.  
  184.     TWindow* GetWindow()
  185.     {
  186.       return (TWindow*)this;
  187.     }
  188.  
  189.     bool     SetDocTitle(const char far* docname, int index)
  190.     {
  191.       return TListBox::SetDocTitle(docname, index);
  192.     }
  193.  
  194.     // Overridden virtuals from TWindow
  195.     //
  196.     bool CanClose()   {return TListBox::CanClose() && Doc->CanClose();}
  197.     bool Create();
  198.  
  199.   protected:
  200.     TDrawDocument* DrawDoc;  // same as Doc member, but cast to derived class
  201.     void LoadData();
  202.     void FormatData(const TLine* line, unsigned int index);
  203.  
  204.     // Message response functions
  205.     void CmPenSize();
  206.     void CmPenColor();
  207.     void CmClear();
  208.     void CmUndo();
  209.     void CmDelete();
  210.  
  211.     // Document notifications
  212.     bool VnIsWindow(HWND hWnd)
  213.     {
  214.       return HWindow == hWnd;
  215.     }
  216.  
  217.     bool VnCommit(bool force);
  218.     bool VnRevert(bool clear);
  219.     bool VnAppend(unsigned int index);
  220.     bool VnDelete(unsigned int index);
  221.     bool VnModify(unsigned int index);
  222.  
  223.   DECLARE_RESPONSE_TABLE(TDrawListView);
  224. };
  225.  
  226. const int vnDrawAppend = vnCustomBase+0;
  227. const int vnDrawDelete = vnCustomBase+1;
  228. const int vnDrawModify = vnCustomBase+2;
  229.  
  230. NOTIFY_SIG(vnDrawAppend, unsigned int)
  231. NOTIFY_SIG(vnDrawDelete, unsigned int)
  232. NOTIFY_SIG(vnDrawModify, unsigned int)
  233.  
  234. #define EV_VN_DRAWAPPEND  VN_DEFINE(vnDrawAppend,  VnAppend,  int)
  235. #define EV_VN_DRAWDELETE  VN_DEFINE(vnDrawDelete,  VnDelete,  int)
  236. #define EV_VN_DRAWMODIFY  VN_DEFINE(vnDrawModify,  VnModify,  int)
  237.  
  238. DEFINE_DOC_TEMPLATE_CLASS(TDrawDocument, TDrawView,   DrawTemplate);
  239. DEFINE_DOC_TEMPLATE_CLASS(TDrawDocument, TDrawListView,   DrawListTemplate);
  240. DrawTemplate drawTpl("Point Files (*.PTS)","*.pts",0,"PTS",dtAutoDelete|dtUpdateDir);
  241. DrawListTemplate drawListTpl("Line List","  *.pts",0,"PTS",dtAutoDelete|dtHidden);
  242.  
  243. void
  244. TLine::SetPen(int penSize)
  245. {
  246.   if (penSize < 1)
  247.     PenSize = 1;
  248.   else
  249.     PenSize = penSize;
  250. }
  251.  
  252. void
  253. TLine::SetPen(TColor& newColor, int penSize)
  254. {
  255.   // If penSize isn't the default (0), set PenSize to the new size.
  256.   if (penSize)
  257.     PenSize = penSize;
  258.  
  259.   Color = newColor;
  260. }
  261.  
  262. bool
  263. TLine::Draw(TDC& dc) const
  264. {
  265.   // Set pen for the dc to the values for this line
  266.   TPen pen(Color, PenSize);
  267.   dc.SelectObject(pen);
  268.  
  269.   // Iterates through the points in the line i.
  270.   TPointsIterator j(*this);
  271.   bool first = true;
  272.  
  273.   while (j) {
  274.     TPoint p = j++;
  275.  
  276.     if (!first)
  277.       dc.LineTo(p);
  278.     else {
  279.       dc.MoveTo(p);
  280.       first = false;
  281.     }
  282.   }
  283.   dc.RestorePen();
  284.   return true;
  285. }
  286.  
  287. ostream&
  288. operator <<(ostream& os, const TLine& line)
  289. {
  290.   // Write the number of points in the line
  291.   os << line.GetItemsInContainer();
  292.  
  293.   // Get and write pen attributes.
  294.   os << ' ' << line.Color << ' ' << line.PenSize;
  295.  
  296.   // Get an iterator for the array of points
  297.   TPointsIterator j(line);
  298.  
  299.   // While the iterator is valid (i.e. we haven't run out of points)
  300.   while(j)
  301.     // Write the point from the iterator and increment the array.
  302.     os << j++;
  303.   os << '\n';
  304.  
  305.   // return the stream object
  306.   return os;
  307. }
  308.  
  309. istream&
  310. operator >>(istream& is, TLine& line)
  311. {
  312.   unsigned numPoints;
  313.   is >> numPoints;
  314.  
  315.   COLORREF color;
  316.   int penSize;
  317.   is >> color >> penSize;
  318.   line.SetPen(TColor(color), penSize);
  319.  
  320.   while (numPoints--) {
  321.     TPoint point;
  322.     is >> point;
  323.     line.Add(point);
  324.   }
  325.  
  326.   // return the stream object
  327.   return is;
  328. }
  329.  
  330. bool
  331. TDrawDocument::Commit(bool force)
  332. {
  333.   if (!IsDirty() && !force)
  334.     return true;
  335.  
  336.   TOutStream* os = OutStream(ofWrite);
  337.   if (!os)
  338.     return false;
  339.  
  340.   // Write the number of lines in the figure
  341.   *os << Lines->GetItemsInContainer();
  342.  
  343.   // Append a description using a resource string
  344.   *os << ' ' << FileInfo << '\n';
  345.  
  346.   // Get an iterator for the array of lines
  347.   TLinesIterator i(*Lines);
  348.  
  349.   // While the iterator is valid (i.e. we haven't run out of lines)
  350.   while (i) {
  351.     // Copy the current line from the iterator and increment the array.
  352.     *os << i++;
  353.   }
  354.   delete os;
  355.  
  356.   SetDirty(false);
  357.   return true;
  358. }
  359.  
  360. bool
  361. TDrawDocument::Revert(bool clear)
  362. {
  363.   if (!TFileDocument::Revert(clear))
  364.     return false;
  365.   if (!clear)
  366.     Open(0);
  367.   return true;
  368. }
  369.  
  370. bool
  371. TDrawDocument::Open(int /*mode*/, const char far* path)
  372. {
  373.   char fileinfo[100];
  374.   Lines = new TLines(5, 0, 5);
  375.   if (path)
  376.     SetDocPath(path);
  377.   if (GetDocPath()) {
  378.     TInStream* is = InStream(ofRead);
  379.     if (!is)
  380.       return false;
  381.  
  382.     unsigned numLines;
  383.     *is >> numLines;
  384.     is->getline(fileinfo, sizeof(fileinfo));
  385.     while (numLines--) {
  386.       TLine line;
  387.       *is >> line;
  388.       Lines->Add(line);
  389.     }
  390.     delete is;
  391.     FileInfo = fileinfo;
  392.   }
  393.   else
  394.     FileInfo = string(*::Module,IDS_FILEINFO);
  395.   SetDirty(false);
  396.   UndoState = UndoNone;
  397.   return true;
  398. }
  399.  
  400. bool
  401. TDrawDocument::Close()
  402. {
  403.   delete Lines;
  404.   Lines = 0;
  405.   return true;
  406. }
  407.  
  408. const TLine*
  409. TDrawDocument::GetLine(unsigned int index)
  410. {
  411.   if (!IsOpen() && !Open(ofRead | ofWrite))
  412.     return 0;
  413.   return index < Lines->GetItemsInContainer() ? &(*Lines)[index] : 0;
  414. }
  415.  
  416. int
  417. TDrawDocument::AddLine(TLine& line)
  418. {
  419.   int index = Lines->GetItemsInContainer();
  420.   Lines->Add(line);
  421.   SetDirty(true);
  422.   NotifyViews(vnDrawAppend, index);
  423.   UndoState = UndoAppend;
  424.   return index;
  425. }
  426.  
  427. void
  428. TDrawDocument::DeleteLine(unsigned int index)
  429. {
  430.   const TLine* oldLine = GetLine(index);
  431.   if (!oldLine)
  432.     return;
  433.   delete UndoLine;
  434.   UndoLine = new TLine(*oldLine);
  435.   Lines->Detach(index);
  436.   SetDirty(true);
  437.   NotifyViews(vnDrawDelete, index);
  438.   UndoState = UndoDelete;
  439. }
  440.  
  441. void
  442. TDrawDocument::ModifyLine(TLine& line, unsigned int index)
  443. {
  444.   delete UndoLine;
  445.   UndoLine = new TLine((*Lines)[index]);
  446.   SetDirty(true);
  447.   (*Lines)[index] = line;
  448.   NotifyViews(vnDrawModify, index);
  449.   UndoState = UndoModify;
  450.   UndoIndex = index;
  451. }
  452.  
  453. void
  454. TDrawDocument::Clear()
  455. {
  456.   Lines->Flush();
  457.   NotifyViews(vnRevert, true);
  458. }
  459.  
  460. void
  461. TDrawDocument::Undo()
  462. {
  463.   switch (UndoState) {
  464.     case UndoAppend:
  465.       DeleteLine(Lines->GetItemsInContainer()-1);
  466.       return;
  467.     case UndoDelete:
  468.       AddLine(*UndoLine);
  469.       delete UndoLine;
  470.       UndoLine = 0;
  471.       return;
  472.     case UndoModify:
  473.       TLine* temp = UndoLine;
  474.       UndoLine = 0;
  475.       ModifyLine(*temp, UndoIndex);
  476.       delete temp;
  477.   }
  478. }
  479.  
  480. bool
  481. GetPenSize(TWindow* parent, TLine& line)
  482. {
  483.   char inputText[6];
  484.  
  485.   wsprintf(inputText, "%d", line.PenSize);
  486.   if (TInputDialog(parent, "Line Thickness",
  487.                         "Input a new thickness:",
  488.                         inputText,
  489.                         sizeof(inputText),::Module).Execute() != IDOK)
  490.     return false;
  491.   line.PenSize = atoi(inputText);
  492.  
  493.   if (line.PenSize < 1)
  494.     line.PenSize = 1;
  495.  
  496.   return true;
  497. }
  498.  
  499. bool
  500. GetPenColor(TWindow* parent, TLine& line)
  501. {
  502.   TChooseColorDialog::TData colors;
  503.   static TColor custColors[16] =
  504.   {
  505.     0x010101L, 0x101010L, 0x202020L, 0x303030L,
  506.     0x404040L, 0x505050L, 0x606060L, 0x707070L,
  507.     0x808080L, 0x909090L, 0xA0A0A0L, 0xB0B0B0L,
  508.     0xC0C0C0L, 0xD0D0D0L, 0xE0E0E0L, 0xF0F0F0L
  509.   };
  510.  
  511.   colors.Flags = CC_RGBINIT;
  512.   colors.Color = TColor(line.QueryColor());
  513.   colors.CustColors = custColors;
  514.   if (TChooseColorDialog(parent, colors).Execute() != IDOK)
  515.     return false;
  516.   line.SetPen(colors.Color);
  517.   return true;
  518. }
  519.  
  520. DEFINE_RESPONSE_TABLE1(TDrawView, TWindowView)
  521.   EV_WM_LBUTTONDOWN,
  522.   EV_WM_RBUTTONDOWN,
  523.   EV_WM_MOUSEMOVE,
  524.   EV_WM_LBUTTONUP,
  525.   EV_COMMAND(CM_PENSIZE, CmPenSize),
  526.   EV_COMMAND(CM_PENCOLOR, CmPenColor),
  527.   EV_COMMAND(CM_CLEAR, CmClear),
  528.   EV_COMMAND(CM_UNDO, CmUndo),
  529.   EV_VN_COMMIT,
  530.   EV_VN_REVERT,
  531.   EV_VN_DRAWAPPEND,
  532.   EV_VN_DRAWDELETE,
  533.   EV_VN_DRAWMODIFY,
  534. END_RESPONSE_TABLE;
  535.  
  536. TDrawView::TDrawView(TDrawDocument& doc,TWindow* parent) :
  537.   TWindowView(doc, parent), DrawDoc(&doc)
  538. {
  539.   DragDC  = 0;
  540.   Line    = new TLine(TColor::Black, 1);
  541.   SetViewMenu(new TMenuDescr(IDM_DRAWVIEW));
  542. }
  543.  
  544. void
  545. TDrawView::EvLButtonDown(uint, TPoint& point)
  546. {
  547.   if (!DragDC) {
  548.     SetCapture();
  549.     DragDC = new TClientDC(*this);
  550.     Pen = new TPen(Line->QueryColor(), Line->QueryPenSize());
  551.     DragDC->SelectObject(*Pen);
  552.     DragDC->MoveTo(point);
  553.     Line->Add(point);
  554.   }
  555. }
  556.  
  557. void
  558. TDrawView::EvRButtonDown(uint, TPoint&)
  559. {
  560.   CmUndo();
  561. }
  562.  
  563. void
  564. TDrawView::EvMouseMove(uint, TPoint& point)
  565. {
  566.   if (DragDC) {
  567.     DragDC->LineTo(point);
  568.     Line->Add(point);
  569.   }
  570. }
  571.  
  572. void
  573. TDrawView::EvLButtonUp(uint, TPoint&)
  574. {
  575.   if (DragDC) {
  576.     ReleaseCapture();
  577.     if (Line->GetItemsInContainer() > 1)
  578.       DrawDoc->AddLine(*Line);
  579.     Line->Flush();
  580.     delete DragDC;
  581.     delete Pen;
  582.     DragDC = 0;
  583.   }
  584. }
  585.  
  586. void
  587. TDrawView::CmPenSize()
  588. {
  589.   GetPenSize(this, *Line);
  590. }
  591.  
  592. void
  593. TDrawView::CmPenColor()
  594. {
  595.   GetPenColor(this, *Line);
  596. }
  597.  
  598. void
  599. TDrawView::CmClear()
  600. {
  601.   DrawDoc->Clear();
  602. }
  603.  
  604. void
  605. TDrawView::CmUndo()
  606. {
  607.   DrawDoc->Undo();
  608. }
  609.  
  610. void
  611. TDrawView::Paint(TDC& dc, bool, TRect&)
  612. {
  613.   // Iterates through the array of line objects.
  614.   int i = 0;
  615.   const TLine* line;
  616.   while ((line = DrawDoc->GetLine(i++)) != 0)
  617.     line->Draw(dc);
  618. }
  619.  
  620. bool
  621. TDrawView::VnCommit(bool /*force*/)
  622. {
  623.   // nothing to do here, no data held in view
  624.   return true;
  625. }
  626.  
  627. bool
  628. TDrawView::VnRevert(bool /*clear*/)
  629. {
  630.   Invalidate();  // force full repaint
  631.   return true;
  632. }
  633.  
  634. bool
  635. TDrawView::VnAppend(unsigned int index)
  636. {
  637.   TClientDC dc(*this);
  638.   const TLine* line = DrawDoc->GetLine(index);
  639.   line->Draw(dc);
  640.   return true;
  641. }
  642.  
  643. bool
  644. TDrawView::VnModify(unsigned int /*index*/)
  645. {
  646.   Invalidate();  // force full repaint
  647.   return true;
  648. }
  649.  
  650. bool
  651. TDrawView::VnDelete(unsigned int /*index*/)
  652. {
  653.   Invalidate();  // force full repaint
  654.   return true;
  655. }
  656.  
  657. DEFINE_RESPONSE_TABLE1(TDrawListView, TListBox)
  658.   EV_COMMAND(CM_PENSIZE, CmPenSize),
  659.   EV_COMMAND(CM_PENCOLOR, CmPenColor),
  660.   EV_COMMAND(CM_CLEAR, CmClear),
  661.   EV_COMMAND(CM_UNDO, CmUndo),
  662.   EV_COMMAND(CM_DELETE, CmDelete),
  663.   EV_VN_ISWINDOW,
  664.   EV_VN_COMMIT,
  665.   EV_VN_REVERT,
  666.   EV_VN_DRAWAPPEND,
  667.   EV_VN_DRAWDELETE,
  668.   EV_VN_DRAWMODIFY,
  669. END_RESPONSE_TABLE;
  670.  
  671. TDrawListView::TDrawListView(TDrawDocument& doc,TWindow* parent) :
  672.   TView(doc), TListBox(parent, GetNextViewId(), 0,0,0,0), DrawDoc(&doc)
  673. {
  674.   Attr.Style &= ~(WS_BORDER | LBS_SORT);
  675.   Attr.Style |= LBS_NOINTEGRALHEIGHT;
  676.   Attr.AccelTable = IDA_DRAWLISTVIEW;
  677.   SetViewMenu(new TMenuDescr(IDM_DRAWLISTVIEW,0,1,0,0,0,0));
  678. }
  679.  
  680. bool
  681. TDrawListView::Create()
  682. {
  683.   TListBox::Create();
  684.   LoadData();
  685.   return true;
  686. }
  687.  
  688. void
  689. TDrawListView::LoadData()
  690. {
  691.   ClearList();
  692.   int i = 0;
  693.   const TLine* line;
  694.   while ((line = DrawDoc->GetLine(i)) != 0)
  695.     FormatData(line, i++);
  696.  
  697.   SetSelIndex(0);
  698. }
  699.  
  700. void
  701. TDrawListView::FormatData(const TLine* line, int unsigned index)
  702. {
  703.   char buf[80];
  704.   TColor color(line->QueryColor());
  705.   wsprintf(buf, "Color = R%d G%d B%d, Size = %d, Points = %d",
  706.            color.Red(), color.Green(), color.Blue(),
  707.            line->QueryPenSize(), line->GetItemsInContainer());
  708.   DeleteString(index);
  709.   InsertString(buf, index);
  710.   SetSelIndex(index);
  711. }
  712.  
  713. void
  714. TDrawListView::CmPenSize()
  715. {
  716.   int index = GetSelIndex();
  717.   const TLine* line = DrawDoc->GetLine(index);
  718.   if (line) {
  719.     TLine* newline = new TLine(*line);
  720.     if (GetPenSize(this, *newline))
  721.       DrawDoc->ModifyLine(*newline, index);
  722.     delete newline;
  723.   }
  724. }
  725.  
  726. void
  727. TDrawListView::CmPenColor()
  728. {
  729.   int index = GetSelIndex();
  730.   const TLine* line = DrawDoc->GetLine(index);
  731.   if (line) {
  732.     TLine* newline = new TLine(*line);
  733.     if (GetPenColor(this, *newline))
  734.       DrawDoc->ModifyLine(*newline, index);
  735.     delete newline;
  736.   }
  737. }
  738.  
  739. void
  740. TDrawListView::CmClear()
  741. {
  742.   DrawDoc->Clear();
  743. }
  744.  
  745. void
  746. TDrawListView::CmUndo()
  747. {
  748.   DrawDoc->Undo();
  749. }
  750.  
  751. void
  752. TDrawListView::CmDelete()
  753. {
  754.   DrawDoc->DeleteLine(GetSelIndex());
  755. }
  756.  
  757. bool
  758. TDrawListView::VnCommit(bool /*force*/)
  759. {
  760.   return true;
  761. }
  762.  
  763. bool
  764. TDrawListView::VnRevert(bool /*clear*/)
  765. {
  766.   LoadData();
  767.   return true;
  768. }
  769.  
  770. bool
  771. TDrawListView::VnAppend(unsigned int index)
  772. {
  773.   const TLine* line = DrawDoc->GetLine(index);
  774.   FormatData(line, index);
  775.   SetSelIndex(index);
  776.   return true;
  777. }
  778.  
  779. bool
  780. TDrawListView::VnDelete(unsigned int index)
  781. {
  782.   DeleteString(index);
  783.   HandleMessage(WM_KEYDOWN,VK_DOWN); // force selection
  784.   return true;
  785. }
  786.  
  787. bool
  788. TDrawListView::VnModify(unsigned int index)
  789. {
  790.   const TLine* line = DrawDoc->GetLine(index);
  791.   FormatData(line, index);
  792.   return true;
  793. }
  794.  
  795. static char* PropNames[] = {
  796.   "Line Count",                  // LineCount
  797.   "Description",                         // Description
  798. };
  799.  
  800. static int PropFlags[] = {
  801.   pfGetBinary|pfGetText, // LineCount
  802.   pfGetText,             // Description
  803. };
  804.  
  805. const char*
  806. TDrawDocument::PropertyName(int index)
  807. {
  808.   if (index <= PrevProperty)
  809.     return TFileDocument::PropertyName(index);
  810.   else if (index < NextProperty)
  811.     return PropNames[index-PrevProperty-1];
  812.   else
  813.     return 0;
  814. }
  815.  
  816. int
  817. TDrawDocument::PropertyFlags(int index)
  818. {
  819.   if (index <= PrevProperty)
  820.     return TFileDocument::PropertyFlags(index);
  821.   else if (index < NextProperty)
  822.     return PropFlags[index-PrevProperty-1];
  823.   else
  824.     return 0;
  825. }
  826.  
  827. int
  828. TDrawDocument::FindProperty(const char far* name)
  829. {
  830.   for (int i=0; i < NextProperty-PrevProperty-1; i++)
  831.     if (strcmp(PropNames[i], name) == 0)
  832.       return i+PrevProperty+1;
  833.   return 0;
  834. }
  835.  
  836. int
  837. TDrawDocument::GetProperty(int prop, void far* dest, int textlen)
  838. {
  839.   switch(prop) {
  840.     case LineCount: {
  841.       int count = Lines->GetItemsInContainer();
  842.       if (!textlen) {
  843.         *(int far*)dest = count;
  844.         return sizeof(int);
  845.       }
  846.       return wsprintf((char far*)dest, "%d", count);
  847.     }
  848.  
  849.     case Description: {
  850.       char* temp = new char[textlen]; // need local copy for medium model
  851.       int len    = FileInfo.copy(temp, textlen);
  852.       strcpy((char far*)dest, temp);
  853.       return len;
  854.     }
  855.   }
  856.   return TFileDocument::GetProperty(prop, dest, textlen);
  857. }
  858.