home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / LISTVIEW.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  8.2 KB  |  356 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1993, 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Implements class TListView
  6. //----------------------------------------------------------------------------
  7. #pragma hdrignore SECTION
  8. #include <owl/owlpch.h>
  9. #include <owl/listview.h>
  10. #include <owl/listview.rh>
  11. #include <owl/docview.rh>
  12. #include <owl/inputdia.h>
  13.  
  14. DIAG_DECLARE_GROUP(OwlDocView);        // General Doc/View diagnostic group
  15.  
  16. #if !defined(SECTION) || SECTION == 1
  17.  
  18. const char VirtualLastLineStr[] = "---";  // Last virtual line appended to list
  19.  
  20. //  class TListView
  21. //  ----- ---------
  22. //
  23. DEFINE_RESPONSE_TABLE1(TListView, TListBox)
  24.   EV_COMMAND(CM_EDITUNDO,   CmEditUndo),
  25.   EV_COMMAND(CM_EDITCUT,    CmEditCut),
  26.   EV_COMMAND(CM_EDITCOPY,   CmEditCopy),
  27.   EV_COMMAND(CM_EDITPASTE,  CmEditPaste),
  28.   EV_COMMAND(CM_EDITCLEAR,  CmEditClear),
  29.   EV_COMMAND(CM_EDITDELETE, CmEditDelete),
  30.   EV_COMMAND(CM_EDITADD,    CmEditAdd),
  31.   EV_COMMAND(CM_EDITEDIT,   CmEditItem),
  32.   EV_WM_GETDLGCODE,
  33.   EV_NOTIFY_AT_CHILD(LBN_DBLCLK, CmEditItem),
  34.   EV_NOTIFY_AT_CHILD(LBN_SELCHANGE, CmSelChange),
  35.   EV_VN_DOCCLOSED,
  36.   EV_VN_ISWINDOW,
  37.   EV_VN_ISDIRTY,
  38.   EV_VN_COMMIT,
  39.   EV_VN_REVERT,
  40. END_RESPONSE_TABLE;
  41.  
  42. TListView::TListView(TDocument& doc, TWindow* parent)
  43. :
  44.   TView(doc),
  45.   TListBox(parent, GetNextViewId(), 0,0,0,0),
  46.   Origin(0),
  47.   MaxWidth(0),
  48.   DirtyFlag(false)
  49. {
  50.   Attr.Style &= ~(LBS_SORT);
  51.   Attr.Style |= (WS_HSCROLL | LBS_NOINTEGRALHEIGHT);
  52.   Attr.AccelTable = IDA_LISTVIEW;
  53.   if (::FindResource(*GetModule(), TResId(IDM_LISTVIEW), RT_MENU))
  54.     SetViewMenu(new TMenuDescr(IDM_LISTVIEW, 0,1,0,0,0,1, GetModule()));
  55. }
  56.  
  57. int
  58. TListView::AddString(const char far* str)
  59. {
  60.   long style = GetWindowLong(GWL_STYLE);
  61.   if (!(style & LBS_SORT)) {
  62.     int itemsInListBox = GetCount();
  63.     if (itemsInListBox > 0) {
  64.       // before the end of list marker
  65.       return InsertString(str, itemsInListBox-1);
  66.     }
  67.   }
  68.   return TListBox::AddString(str);
  69. }
  70.  
  71. void
  72. TListView::SetExtent(const char far* str)
  73. {
  74.   int len;
  75.   if ((len = strlen(str)) == 0)
  76.     return;
  77.  
  78.   HDC hdc = ::GetDC(HWindow);
  79.   TSize extent;
  80.   ::GetTextExtentPoint(hdc, str, len, &extent);
  81.   extent.cx += 2; // room for focus rectangle
  82.  
  83.   if (extent.cx > MaxWidth)
  84.     SetHorizontalExtent(MaxWidth = extent.cx);
  85.  
  86.   ::ReleaseDC(HWindow, hdc);
  87. }
  88.  
  89. bool
  90. TListView::VnDocClosed(int omode)
  91. {
  92.   if (DirtyFlag == 2 || !(omode & ofWrite))  // make sure someone else's write
  93.     return false;
  94.   int top = GetTopIndex();
  95.   int sel = GetSelIndex();
  96.   LoadData(top, sel);
  97.   return true;
  98. }
  99.  
  100. bool
  101. TListView::LoadData(int top, int sel)
  102. {
  103.   CmEditClear();    // Clear list & remove virtual last line temporarily
  104.   DeleteString(0);
  105.  
  106.   long style = GetWindowLong(GWL_STYLE);
  107.   if (!(style & LBS_SORT))
  108.     TListBox::AddString(VirtualLastLineStr);     // Append virtual last line
  109.  
  110.   DirtyFlag = false;
  111.  
  112.   bool status = true;
  113.   istream* inStream;
  114.   if ((inStream = Doc->InStream(ios::in)) == 0) {
  115.     Doc->PostError(IDS_UNABLEOPEN, MB_OK);
  116.     return false;
  117.   }
  118.   for (;;) {
  119.     char buf[100+1];
  120.     inStream->getline(buf, sizeof(buf)-1);
  121.     if (!inStream->gcount() && !inStream->good()) {
  122.       status = ToBool(inStream->eof());
  123.       break;
  124.     }
  125.     AddString(buf);
  126.     SetExtent(buf);
  127.   }
  128.   SetTopIndex(top);
  129.   SetSelIndex(sel);
  130.   delete inStream;   // close file in case process switch
  131.   if (!status)
  132.     Doc->PostError(IDS_READERROR, MB_OK);
  133.   return status;
  134. }
  135.  
  136. bool
  137. TListView::Create()
  138. {
  139.   TRY {
  140.     TListBox::Create();   // throws exception TWindow::TXWindow
  141.   }
  142.   CATCH( (TXOwl& x) {
  143.     Doc->PostError(IDS_NOMEMORYFORVIEW, MB_OK);
  144.     return true;   // cannot return false - throws another exception
  145.   })
  146.   if (Doc->GetDocPath() == 0) {
  147.     CmEditClear();         // perform any clearing initialization
  148.     return true;           // new file, no data to display
  149.   }
  150.   if (!LoadData(0, 0))
  151.     NotOK();
  152.   return true;
  153. }
  154.  
  155. bool
  156. TListView::VnCommit(bool force)
  157. {
  158.   if (!force && !DirtyFlag)
  159.     return true;
  160.  
  161.   ostream* outStream = Doc->OutStream(ios::out);
  162.   if (outStream == 0) {
  163.     Doc->PostError(IDS_UNABLEOPEN, MB_OK);
  164.     return false;
  165.   }
  166.   outStream->seekp(Origin);
  167.   int count = GetCount();
  168.   for (int index = 0; index < count-1; index++) {  // don't write last virtual line
  169.     int len = GetStringLen(index);
  170.     char* buf = new char[len+1];
  171.     GetString(buf, index);
  172.     *outStream << buf << '\n';
  173.     delete buf;
  174.   }
  175.   DirtyFlag = 2;           // to detect our own close notification
  176.  
  177.   bool status = ToBool(outStream->good());
  178.   delete outStream;
  179.   DirtyFlag = false;
  180.   if (!status)
  181.     Doc->PostError(IDS_WRITEERROR, MB_OK);
  182.  
  183.   return status;
  184. }
  185.  
  186. bool
  187. TListView::VnRevert(bool clear)
  188. {
  189.   if (!clear && Doc->GetDocPath() != 0)
  190.     return LoadData(0,0);
  191.   CmEditClear();
  192.   DirtyFlag = false;
  193.   return true;
  194. }
  195.  
  196. uint
  197. TListView::EvGetDlgCode(MSG far*)
  198. {
  199.   uint retVal = (uint)DefaultProcessing();
  200.   retVal |= DLGC_WANTCHARS;
  201.   return retVal;
  202. }
  203.  
  204. void
  205. TListView::CmEditUndo()
  206. {
  207.   MessageBox("Feature not implemented", "Undo", MB_OK);
  208. }
  209.  
  210. void
  211. TListView::CmEditCut()
  212. {
  213.   CmEditCopy();
  214.   CmEditDelete();
  215. }
  216.  
  217. void
  218. TListView::CmEditCopy()
  219. {
  220.   int index = GetSelIndex();
  221.   int count = GetCount();
  222.   if (count <= 1 || index >= count-1)
  223.     return;
  224.  
  225.   TClipboard cb(*this);
  226.   if (cb.EmptyClipboard()) {
  227.     int len = GetStringLen(index);
  228.     HANDLE cbhdl = ::GlobalAlloc(GHND,len+0+1);
  229.     char far* buf = (char far*)::GlobalLock(cbhdl);
  230.     GetString(buf, index);
  231.     ::GlobalUnlock(cbhdl);
  232.     cb.SetClipboardData(CF_TEXT, cbhdl);
  233.   }
  234. }
  235.  
  236. void
  237. TListView::CmEditPaste()
  238. {
  239.   int index = GetSelIndex();
  240.   if (index < 0)
  241.     index = 0;
  242.  
  243.   TClipboard cb(*this);
  244.   if (!cb)
  245.     return;   // clipboard open by another program
  246.  
  247.   HANDLE cbhdl = cb.GetClipboardData(CF_TEXT);
  248.   if (cbhdl) {
  249.     char far* text = (char far*)::GlobalLock(cbhdl);
  250.     InsertString(text, index);
  251.     SetSelIndex(index+1);
  252.     DirtyFlag = true;
  253.     ::GlobalUnlock(cbhdl);
  254.   }
  255. }
  256.  
  257. void
  258. TListView::CmEditDelete()
  259. {
  260.   int count = GetCount();
  261.   int index = GetSelIndex();
  262.   if (count <= 1 || index >= count-1)
  263.     return;
  264.  
  265.   DeleteString(index);
  266.   SetSelIndex(index);
  267.   DirtyFlag = true;
  268. }
  269.  
  270. void
  271. TListView::CmEditClear()
  272. {
  273.   int count = GetCount();
  274.   if (count == 1)
  275.     return;
  276.   if (count) {
  277.     ClearList();
  278.     DirtyFlag = true;
  279.     SetHorizontalExtent(MaxWidth = 0);
  280.   }
  281.   long style = GetWindowLong(GWL_STYLE);
  282.   if (!(style & LBS_SORT))
  283.     TListBox::AddString(VirtualLastLineStr);
  284. }
  285.  
  286. static int linePrompt(TWindow* parent, int index, UINT id,
  287.                       char far* buf, int buflen)
  288. {
  289.   char msg[41];
  290.   wsprintf(msg, parent->GetModule()->LoadString(IDS_LISTNUM).c_str(), index);
  291.   return TInputDialog(parent, msg,
  292.                       parent->GetModule()->LoadString(id).c_str(),
  293.                       buf, buflen).Execute();
  294. }
  295.  
  296. void
  297. TListView::CmEditAdd()
  298. {
  299.   char inputText[101];
  300.   *inputText = 0;
  301.  
  302.   int index = GetSelIndex();
  303.   if (index < 0)
  304.     index = 0;
  305.  
  306.   if (linePrompt(this,index+1,CM_EDITADD,inputText,sizeof(inputText)) == IDOK) {
  307.     InsertString(inputText, index);
  308.     SetSelIndex(index+1);
  309.     SetExtent(inputText);
  310.     DirtyFlag = true;
  311.   }
  312. }
  313.  
  314. void
  315. TListView::CmEditItem()
  316. {
  317.   int index = GetSelIndex();
  318.   if (index < 0 || index >= GetCount()-1)
  319.     return;
  320.  
  321.   char inputText[101];
  322.   GetSelString(inputText, sizeof(inputText)-1);
  323.  
  324.   if (linePrompt(this,index+1,CM_EDITEDIT,inputText,sizeof(inputText))==IDOK) {
  325.     DeleteString(index);
  326.     InsertString(inputText, index);
  327.     SetExtent(inputText);
  328.     SetSelIndex(index);
  329.     DirtyFlag = true;
  330.   }
  331. }
  332.  
  333. #endif
  334. #if !defined(SECTION) || SECTION == 2
  335.  
  336. IMPLEMENT_STREAMABLE2(TListView, TListBox, TView);
  337.  
  338. void*
  339. TListView::Streamer::Read(ipstream& is, uint32 /*version*/) const
  340. {
  341.   ReadBaseObject((TListBox*)GetObject(), is);
  342.   ReadBaseObject((TView*)GetObject(), is);
  343.   is >> GetObject()->Origin;
  344.   return GetObject();
  345. }
  346.  
  347. void
  348. TListView::Streamer::Write(opstream &os) const
  349. {
  350.   WriteBaseObject((TListBox*)GetObject(), os);
  351.   WriteBaseObject((TView*)GetObject(), os);
  352.   os << GetObject()->Origin;
  353. }
  354.  
  355. #endif
  356.