//---------------------------------------------------------------------------- // ObjectWindows // (C) Copyright 1993, 1994 by Borland International, All Rights Reserved // // Implements class TListView //---------------------------------------------------------------------------- #pragma hdrignore SECTION #include #include #include #include #include DIAG_DECLARE_GROUP(OwlDocView); // General Doc/View diagnostic group #if !defined(SECTION) || SECTION == 1 const char VirtualLastLineStr[] = "---"; // Last virtual line appended to list // class TListView // ----- --------- // DEFINE_RESPONSE_TABLE1(TListView, TListBox) EV_COMMAND(CM_EDITUNDO, CmEditUndo), EV_COMMAND(CM_EDITCUT, CmEditCut), EV_COMMAND(CM_EDITCOPY, CmEditCopy), EV_COMMAND(CM_EDITPASTE, CmEditPaste), EV_COMMAND(CM_EDITCLEAR, CmEditClear), EV_COMMAND(CM_EDITDELETE, CmEditDelete), EV_COMMAND(CM_EDITADD, CmEditAdd), EV_COMMAND(CM_EDITEDIT, CmEditItem), EV_WM_GETDLGCODE, EV_NOTIFY_AT_CHILD(LBN_DBLCLK, CmEditItem), EV_NOTIFY_AT_CHILD(LBN_SELCHANGE, CmSelChange), EV_VN_DOCCLOSED, EV_VN_ISWINDOW, EV_VN_ISDIRTY, EV_VN_COMMIT, EV_VN_REVERT, END_RESPONSE_TABLE; TListView::TListView(TDocument& doc, TWindow* parent) : TView(doc), TListBox(parent, GetNextViewId(), 0,0,0,0), Origin(0), MaxWidth(0), DirtyFlag(false) { Attr.Style &= ~(LBS_SORT); Attr.Style |= (WS_HSCROLL | LBS_NOINTEGRALHEIGHT); Attr.AccelTable = IDA_LISTVIEW; if (::FindResource(*GetModule(), TResId(IDM_LISTVIEW), RT_MENU)) SetViewMenu(new TMenuDescr(IDM_LISTVIEW, 0,1,0,0,0,1, GetModule())); } int TListView::AddString(const char far* str) { long style = GetWindowLong(GWL_STYLE); if (!(style & LBS_SORT)) { int itemsInListBox = GetCount(); if (itemsInListBox > 0) { // before the end of list marker return InsertString(str, itemsInListBox-1); } } return TListBox::AddString(str); } void TListView::SetExtent(const char far* str) { int len; if ((len = strlen(str)) == 0) return; HDC hdc = ::GetDC(HWindow); TSize extent; ::GetTextExtentPoint(hdc, str, len, &extent); extent.cx += 2; // room for focus rectangle if (extent.cx > MaxWidth) SetHorizontalExtent(MaxWidth = extent.cx); ::ReleaseDC(HWindow, hdc); } bool TListView::VnDocClosed(int omode) { if (DirtyFlag == 2 || !(omode & ofWrite)) // make sure someone else's write return false; int top = GetTopIndex(); int sel = GetSelIndex(); LoadData(top, sel); return true; } bool TListView::LoadData(int top, int sel) { CmEditClear(); // Clear list & remove virtual last line temporarily DeleteString(0); long style = GetWindowLong(GWL_STYLE); if (!(style & LBS_SORT)) TListBox::AddString(VirtualLastLineStr); // Append virtual last line DirtyFlag = false; bool status = true; istream* inStream; if ((inStream = Doc->InStream(ios::in)) == 0) { Doc->PostError(IDS_UNABLEOPEN, MB_OK); return false; } for (;;) { char buf[100+1]; inStream->getline(buf, sizeof(buf)-1); if (!inStream->gcount() && !inStream->good()) { status = ToBool(inStream->eof()); break; } AddString(buf); SetExtent(buf); } SetTopIndex(top); SetSelIndex(sel); delete inStream; // close file in case process switch if (!status) Doc->PostError(IDS_READERROR, MB_OK); return status; } bool TListView::Create() { TRY { TListBox::Create(); // throws exception TWindow::TXWindow } CATCH( (TXOwl& x) { Doc->PostError(IDS_NOMEMORYFORVIEW, MB_OK); return true; // cannot return false - throws another exception }) if (Doc->GetDocPath() == 0) { CmEditClear(); // perform any clearing initialization return true; // new file, no data to display } if (!LoadData(0, 0)) NotOK(); return true; } bool TListView::VnCommit(bool force) { if (!force && !DirtyFlag) return true; ostream* outStream = Doc->OutStream(ios::out); if (outStream == 0) { Doc->PostError(IDS_UNABLEOPEN, MB_OK); return false; } outStream->seekp(Origin); int count = GetCount(); for (int index = 0; index < count-1; index++) { // don't write last virtual line int len = GetStringLen(index); char* buf = new char[len+1]; GetString(buf, index); *outStream << buf << '\n'; delete buf; } DirtyFlag = 2; // to detect our own close notification bool status = ToBool(outStream->good()); delete outStream; DirtyFlag = false; if (!status) Doc->PostError(IDS_WRITEERROR, MB_OK); return status; } bool TListView::VnRevert(bool clear) { if (!clear && Doc->GetDocPath() != 0) return LoadData(0,0); CmEditClear(); DirtyFlag = false; return true; } uint TListView::EvGetDlgCode(MSG far*) { uint retVal = (uint)DefaultProcessing(); retVal |= DLGC_WANTCHARS; return retVal; } void TListView::CmEditUndo() { MessageBox("Feature not implemented", "Undo", MB_OK); } void TListView::CmEditCut() { CmEditCopy(); CmEditDelete(); } void TListView::CmEditCopy() { int index = GetSelIndex(); int count = GetCount(); if (count <= 1 || index >= count-1) return; TClipboard cb(*this); if (cb.EmptyClipboard()) { int len = GetStringLen(index); HANDLE cbhdl = ::GlobalAlloc(GHND,len+0+1); char far* buf = (char far*)::GlobalLock(cbhdl); GetString(buf, index); ::GlobalUnlock(cbhdl); cb.SetClipboardData(CF_TEXT, cbhdl); } } void TListView::CmEditPaste() { int index = GetSelIndex(); if (index < 0) index = 0; TClipboard cb(*this); if (!cb) return; // clipboard open by another program HANDLE cbhdl = cb.GetClipboardData(CF_TEXT); if (cbhdl) { char far* text = (char far*)::GlobalLock(cbhdl); InsertString(text, index); SetSelIndex(index+1); DirtyFlag = true; ::GlobalUnlock(cbhdl); } } void TListView::CmEditDelete() { int count = GetCount(); int index = GetSelIndex(); if (count <= 1 || index >= count-1) return; DeleteString(index); SetSelIndex(index); DirtyFlag = true; } void TListView::CmEditClear() { int count = GetCount(); if (count == 1) return; if (count) { ClearList(); DirtyFlag = true; SetHorizontalExtent(MaxWidth = 0); } long style = GetWindowLong(GWL_STYLE); if (!(style & LBS_SORT)) TListBox::AddString(VirtualLastLineStr); } static int linePrompt(TWindow* parent, int index, UINT id, char far* buf, int buflen) { char msg[41]; wsprintf(msg, parent->GetModule()->LoadString(IDS_LISTNUM).c_str(), index); return TInputDialog(parent, msg, parent->GetModule()->LoadString(id).c_str(), buf, buflen).Execute(); } void TListView::CmEditAdd() { char inputText[101]; *inputText = 0; int index = GetSelIndex(); if (index < 0) index = 0; if (linePrompt(this,index+1,CM_EDITADD,inputText,sizeof(inputText)) == IDOK) { InsertString(inputText, index); SetSelIndex(index+1); SetExtent(inputText); DirtyFlag = true; } } void TListView::CmEditItem() { int index = GetSelIndex(); if (index < 0 || index >= GetCount()-1) return; char inputText[101]; GetSelString(inputText, sizeof(inputText)-1); if (linePrompt(this,index+1,CM_EDITEDIT,inputText,sizeof(inputText))==IDOK) { DeleteString(index); InsertString(inputText, index); SetExtent(inputText); SetSelIndex(index); DirtyFlag = true; } } #endif #if !defined(SECTION) || SECTION == 2 IMPLEMENT_STREAMABLE2(TListView, TListBox, TView); void* TListView::Streamer::Read(ipstream& is, uint32 /*version*/) const { ReadBaseObject((TListBox*)GetObject(), is); ReadBaseObject((TView*)GetObject(), is); is >> GetObject()->Origin; return GetObject(); } void TListView::Streamer::Write(opstream &os) const { WriteBaseObject((TListBox*)GetObject(), os); WriteBaseObject((TView*)GetObject(), os); os << GetObject()->Origin; } #endif