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

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1992, 1993 by Borland International
  3. //   Implements class TODListView
  4. //----------------------------------------------------------------------------
  5. #include <owl\owlpch.h>
  6. #include <owl\docmanag.h>
  7. #include <owl\filedoc.h>
  8. #include <owl\inputdia.h>
  9. #include "odlistbx.h"
  10. #include "odlistvw.rc"
  11.  
  12. //  class TODListView
  13. //  ----- -----------
  14. //
  15. class _DOCVIEWCLASS TODListView : public TODListBox, public TView {
  16.   public:
  17.     TODListView(TDocument& doc, TWindow* parent = 0);
  18.    ~TODListView();
  19.     static const char far* StaticName() {return "OD List View";}  // put in resource
  20.     BOOL DirtyFlag;
  21.  
  22.     //
  23.     // overridden virtuals from TView
  24.     //
  25.     const char far*  GetViewName() {return StaticName();}
  26.     TWindow* GetWindow()  {return (TWindow*)this;}
  27.     BOOL     SetDocTitle(const char far* docname, int index)
  28.                           {return TODListBox::SetDocTitle(docname, index); }
  29.     //
  30.     // overridden virtuals from TWindow
  31.     //
  32.     BOOL Create();
  33.     UINT EvGetDlgCode(MSG far*);
  34.     BOOL CanClose()   {return TODListBox::CanClose() && Doc->CanClose();}
  35.  
  36.   protected:
  37.     long Origin;
  38.     BOOL LoadData(int top, int sel);
  39.     //
  40.     // message response functions
  41.     //
  42.     void CmEditUndo();
  43.     void CmEditCut();
  44.     void CmEditCopy();
  45.     void CmEditPaste();
  46.     void CmEditDelete();
  47.     void CmEditClear();
  48.     void CmEditAdd();
  49.     void CmEditItem();
  50. //  void CmLineIndent();
  51. //  void CmLineUnindent();
  52.     BOOL VnCommit(BOOL force);
  53.     BOOL VnRevert(BOOL clear);
  54.     BOOL VnIsWindow(HWND hWnd) {return HWindow == hWnd;}
  55.     BOOL VnIsDirty()  {return DirtyFlag;}
  56.     BOOL VnDocClosed(int omode);
  57.     void EvDestroy();
  58.     void CmSelChange() {} // to prevent interpreting as unprocessed accelerator
  59.  
  60.   DECLARE_RESPONSE_TABLE(TODListView);
  61.   DECLARE_STREAMABLE(,TODListView,1);
  62. };
  63.  
  64.  
  65. const char VirtualLastLineStr[] = "---";  // Last virtual line appended to list
  66.  
  67. DEFINE_RESPONSE_TABLE1(TODListView, TODListBox)
  68.   EV_COMMAND(CM_ODLISTUNDO,    CmEditUndo),
  69.   EV_COMMAND(CM_ODLISTCUT,     CmEditCut),
  70.   EV_COMMAND(CM_ODLISTCOPY,    CmEditCopy),
  71.   EV_COMMAND(CM_ODLISTPASTE,   CmEditPaste),
  72.   EV_COMMAND(CM_ODLISTCLEAR,   CmEditClear),
  73.   EV_COMMAND(CM_ODLISTDELETE,  CmEditDelete),
  74.   EV_COMMAND(CM_ODLISTADD,     CmEditAdd),
  75.   EV_COMMAND(CM_ODLISTEDIT,    CmEditItem),
  76.   EV_WM_GETDLGCODE,
  77.   EV_WM_DESTROY,
  78.   EV_NOTIFY_AT_CHILD(LBN_DBLCLK,    CmEditItem),
  79.   EV_NOTIFY_AT_CHILD(LBN_SELCHANGE, CmSelChange),
  80.   EV_VN_DOCCLOSED,
  81.   EV_VN_ISWINDOW,
  82.   EV_VN_ISDIRTY,
  83.   EV_VN_COMMIT,
  84.   EV_VN_REVERT,
  85. END_RESPONSE_TABLE;
  86.  
  87. DEFINE_DOC_TEMPLATE_CLASS(TFileDocument, TODListView, ODLBTemplate);
  88. ODLBTemplate odBinTpl("ODListBox, All files","*.*", 0, "TXT",dtAutoDelete);
  89. ODLBTemplate odTxtTpl("ODStrings, All files","*.*", 0, "TXT",dtAutoDelete);
  90.  
  91. TODListView::TODListView(TDocument& doc, TWindow* /*parent*/)
  92.    : TView(doc), TODListBox(GetNextViewId()),
  93.      Origin(0), DirtyFlag(FALSE)
  94. {
  95.   Attr.Style &= ~(WS_BORDER | LBS_SORT);
  96.   Attr.Style |= (WS_HSCROLL | LBS_NOINTEGRALHEIGHT);
  97.   if (doc.GetTemplate() == &odTxtTpl)
  98.     Attr.Style |= LBS_HASSTRINGS;
  99.   Attr.AccelTable = IDA_ODLISTVIEW;
  100.   SetViewMenu(new TMenuDescr(IDM_ODLISTVIEW,0,1,0,0,0,1));
  101. }
  102.  
  103. BOOL
  104. TODListView::LoadData(int top, int sel)
  105. {
  106.   CmEditClear();
  107.   DeleteString(0);
  108.   DirtyFlag = FALSE;
  109.  
  110.   istream* inStream;
  111.   if ((inStream = Doc->InStream(ios::in)) == 0)
  112.     return FALSE;
  113.  
  114.   for (;;) {
  115.     char buf[100+1];
  116.     inStream->getline(buf, sizeof(buf)-1);
  117.     if (!inStream->gcount() && !inStream->good())
  118.       break;  // if EOF or error
  119.     char* str;
  120.     if (Attr.Style & LBS_HASSTRINGS) {   // strings stored in list box
  121.       str = buf;
  122.     } else {
  123.       str = new char[strlen(buf)+1];
  124.       strcpy(str, buf);
  125.     }
  126.     AddString(str);
  127.   }
  128.   AddString(VirtualLastLineStr);
  129.   SetSelIndex(top);
  130.   SetSelIndex(sel);
  131.   delete inStream;   // close file in case process switch
  132.   return TRUE;
  133. }
  134.  
  135. BOOL
  136. TODListView::Create()
  137. {
  138.   DirtyFlag = FALSE;
  139.   TODListBox::Create();   // throws exception TXInvalidWindow
  140.   if (Doc->GetDocPath() == 0) {  
  141.     CmEditClear();         // perform any clearing initialization
  142.     return TRUE;           // new file, no data to display
  143.   }
  144.   if (!LoadData(0, 0))
  145.     NotOK();
  146.   return TRUE;
  147. }
  148.  
  149. BOOL
  150. TODListView::VnDocClosed(int omode)
  151. {
  152.   int top;
  153.   int sel;
  154.   if (DirtyFlag == 2 || !(omode & ofWrite))  // make sure someone else's write
  155.     return FALSE;
  156.   top = GetTopIndex();
  157.   sel = GetSelIndex();
  158.   LoadData(top, sel);
  159.   return TRUE;
  160. }
  161.  
  162. BOOL
  163. TODListView::VnCommit(BOOL force)
  164. {
  165.   if (!force && !DirtyFlag)
  166.     return TRUE;
  167.  
  168.   ostream* outStream;
  169.   if ((outStream = Doc->OutStream(ios::out)) == 0)
  170.     return FALSE;
  171.   outStream->seekp(Origin);
  172.  
  173.   char* buf = 0;  // initialized only to prevent warning about use before def
  174.   int buflen = 0;
  175.   int count = GetCount();
  176.   for (int index = 0; index < count-1; index++) {  // don't write last virtual line
  177.     int len;
  178.     char far* str;
  179.     if (Attr.Style & LBS_HASSTRINGS) {
  180.       len = GetStringLen(index);
  181.     } else {
  182.       str = (char far*)GetItemData(index);
  183.       len = str ? strlen(str) : 0;
  184.     }
  185.     if (len != 0) {
  186.       if (len >= buflen) {
  187.         if (buflen != 0)
  188.           delete buf;
  189.         buf = new char[buflen = len+1];
  190.       }
  191.       if (Attr.Style & LBS_HASSTRINGS)
  192.         GetString(buf, index);
  193.       else
  194.         strcpy(buf, str);
  195.       *outStream << buf;
  196.     }
  197.     *outStream << '\n';
  198.   }
  199.   if (buflen != 0)
  200.     delete buf;
  201.   DirtyFlag = 2;           // to detect our own close notification
  202.   delete outStream;
  203.   DirtyFlag = FALSE;
  204.   return TRUE;
  205. }
  206.  
  207. BOOL
  208. TODListView::VnRevert(BOOL clear)
  209. {
  210.   if (!clear && Doc->GetDocPath() != 0)
  211.     return LoadData(0,0);
  212.   CmEditClear();
  213.   DirtyFlag = FALSE;
  214.   return TRUE;
  215. }
  216.  
  217. UINT
  218. TODListView::EvGetDlgCode(MSG far*)
  219. {
  220.   UINT retVal = (UINT)DefaultProcessing();
  221.   retVal |= DLGC_WANTCHARS;
  222.   return retVal;
  223. }
  224.  
  225. void
  226. TODListView::CmEditUndo()
  227. {
  228.   MessageBox("Feature not implemented", "Undo", MB_OK);
  229. }
  230.  
  231. void
  232. TODListView::CmEditCut()
  233. {
  234.   CmEditCopy();
  235.   CmEditDelete();
  236. }
  237.  
  238. void
  239. TODListView::CmEditCopy()
  240. {
  241.   int index = GetSelIndex();
  242.   int count = GetCount();
  243.   if (count <= 1 || index >= count-1)
  244.     return;
  245.  
  246.   char far* str;
  247.   int len;
  248.   if (Attr.Style & LBS_HASSTRINGS) {  // strings stored in list box
  249.     len = GetStringLen(index);
  250.   } else {
  251.     str = (char far*)GetItemData(index);
  252.     len = strlen(str);
  253.   }
  254.  
  255.   TClipboard cb(*this);
  256.   if (cb.EmptyClipboard()) {
  257.     HANDLE cbhdl = ::GlobalAlloc(GHND, len+0+1);
  258.     char far* gbuf = (char far*)::GlobalLock(cbhdl);
  259.     if (Attr.Style & LBS_HASSTRINGS) {  // strings stored in list box
  260.       GetString(gbuf, index);
  261.     } else {
  262.       strcpy(gbuf, str);
  263.     }
  264.     ::GlobalUnlock(cbhdl);
  265.     cb.SetClipboardData(CF_TEXT, cbhdl);
  266.   }
  267. }
  268.  
  269. void
  270. TODListView::CmEditPaste()
  271. {
  272.   int index = GetSelIndex();
  273.   if (index < 0)
  274.     index = 0;
  275.  
  276.   TClipboard cb(*this);
  277.   if (!cb)
  278.     return;  // clipboard open by another window
  279.  
  280.   HANDLE cbhdl = cb.GetClipboardData(CF_TEXT);
  281.   if (cbhdl) {
  282.     char far* text = (char far*)::GlobalLock(cbhdl);
  283.     char far* str;
  284.     if (Attr.Style & LBS_HASSTRINGS) {   // strings stored in list box
  285.       str = text;
  286.     } else {
  287.       str = new char[strlen(text)+1];
  288.       strcpy(str, text);
  289.     }
  290.     InsertString(str, index);
  291.     SetSelIndex(index+1);
  292.     DirtyFlag = TRUE;
  293.     ::GlobalUnlock(cbhdl);
  294.   }
  295. }
  296.  
  297. void
  298. TODListView::CmEditDelete()
  299. {
  300.   int count = GetCount();
  301.   int index = GetSelIndex();
  302.   if (count <= 1 || index >= count-1)
  303.     return;
  304.  
  305.   ODItemInfo item;
  306.   item.Hdc = ::GetDC(*this);
  307.   item.Index = index;
  308.   item.Data  = (void far*)GetItemData(index);
  309.   item.State = 0;
  310.   GetItemInfo(item);
  311.   ::ReleaseDC(*this, item.Hdc);
  312.   if (item.Extent.cx == MaxWidth)
  313.     SetHorizontalExtent(MaxWidth = 0); // force recalculate max width
  314.   if (!(Attr.Style & LBS_HASSTRINGS))  // strings not stored in list box
  315.     delete item.Data;
  316.  
  317.   DeleteString(index);
  318.   SetSelIndex(index);
  319.   DirtyFlag = TRUE;
  320. }
  321.  
  322. void
  323. TODListView::CmEditClear()
  324. {
  325.   int count = GetCount();
  326.   if (count == 1)
  327.     return;
  328.   if (count) {
  329.     if (!(Attr.Style & LBS_HASSTRINGS))  // strings not stored in list box
  330.       for (int index = 0; index < count-1; index++)
  331.         delete (char far*)GetItemData(index);
  332.     ClearList();
  333.     DirtyFlag = TRUE;
  334.     SetHorizontalExtent(MaxWidth = 0);
  335.   }
  336.   AddString(VirtualLastLineStr);
  337. }
  338.  
  339. TODListView::~TODListView()
  340. {
  341.   if (HWindow)
  342.     CmEditClear();
  343. }
  344.  
  345. void
  346. TODListView::EvDestroy()
  347. {
  348.   CmEditClear();
  349.   TWindow::EvDestroy();
  350. }
  351.  
  352. static int linePrompt(TWindow* parent, int index, UINT id, char far* buf,int buflen)
  353. {
  354.   char msg[41];
  355.   wsprintf(msg, string(*parent->GetModule(), IDS_ODLISTNUM).c_str(), index);
  356.   const char far* prompt = string(*parent->GetModule(), id).c_str();
  357.   return TInputDialog(parent, msg, prompt, buf, buflen).Execute();
  358. }
  359.  
  360. void
  361. TODListView::CmEditAdd()
  362. {
  363.   char inputText[80];
  364.   *inputText = 0;
  365.  
  366.   int index = GetSelIndex();
  367.   if (index < 0)
  368.     index = 0;
  369.  
  370.   if (linePrompt(this,index+1,CM_ODLISTADD,inputText,sizeof(inputText))==IDOK) {
  371.     char far* str;
  372.     if (Attr.Style & LBS_HASSTRINGS) {   // strings stored in list box
  373.       str = inputText;
  374.     } else {
  375.       str = new char[strlen(inputText)+1];
  376.       strcpy(str, inputText);
  377.     }
  378.     InsertString(str, index);
  379.     SetSelIndex(index+1);
  380.     DirtyFlag = TRUE;
  381.   }
  382. }
  383.  
  384. void
  385. TODListView::CmEditItem()
  386. {
  387.   int index = GetSelIndex();
  388.   if (index < 0 || index >= GetCount()-1)
  389.     return;
  390.  
  391.   int len;
  392.   char* inputText;
  393.   if (Attr.Style & LBS_HASSTRINGS) { // strings stored in list box
  394.     len = GetStringLen(index);
  395.     inputText = new char[len + 81];
  396.     GetString(inputText, index);
  397.   } else {
  398.     char far* str = (char far*)GetItemData(index);
  399.     len = strlen(str);
  400.     inputText = new char[len + 81];
  401.     strcpy(inputText, str);
  402.   }
  403.   if (linePrompt(this,index+1,CM_ODLISTEDIT,inputText, len + 81)==IDOK) {
  404.     char far* str;
  405.     if (Attr.Style & LBS_HASSTRINGS) {  // strings stored in list box
  406.       str = inputText;
  407.     } else {
  408.       delete (char far*)GetItemData(index);
  409.       str = strnewdup(inputText);
  410.     }
  411.     DeleteString(index);
  412.     InsertString(str, index);
  413.     SetSelIndex(index);
  414.     DirtyFlag = TRUE;
  415.   }  
  416.   delete inputText;
  417. }
  418.  
  419. IMPLEMENT_STREAMABLE2(TODListView, TODListBox, TView);
  420.  
  421. void *
  422. TODListView::Streamer::Read(ipstream &is, uint32 /* version */) const
  423. {
  424.   ReadBaseObject((TODListBox*)GetObject(), is);
  425.   ReadBaseObject((TView*)GetObject(), is);
  426.   is >> GetObject()->Origin;
  427.   GetObject()->DirtyFlag = FALSE;
  428.   return GetObject();
  429. }
  430.  
  431. void
  432. TODListView::Streamer::Write(opstream &os) const
  433. {
  434.   WriteBaseObject((TODListBox*)GetObject(), os);
  435.   WriteBaseObject((TView*)GetObject(), os);
  436.   os << GetObject()->Origin;
  437. }
  438.