home *** CD-ROM | disk | FTP | other *** search
- // ter_mfc.cpp : implementation file
- //
-
- #include "stdafx.h"
-
- #include "ter_mfc.h"
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char BASED_CODE THIS_FILE[] = __FILE__;
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
- // CTer
-
- IMPLEMENT_DYNAMIC(CTer, CWnd)
-
- BEGIN_MESSAGE_MAP(CTer, CWnd)
- //{{AFX_MSG_MAP(CTer)
- // NOTE - the ClassWizard will add and remove mapping macros here.
- //}}AFX_MSG_MAP
-
- END_MESSAGE_MAP()
-
- /////////////////////////////////////////////////////////////////////////////
- // Contruction
-
- CTer::CTer()
- {
- // Variable initialization
- m_hBuffer=0;
- m_BufLen=0;
- }
-
- CTer::~CTer()
- {
- DestroyWindow();
- }
-
- BOOL CTer::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
- {
- LoadTerControl();
-
- return CWnd::Create(TER_CLASS, "", dwStyle ? dwStyle : DefaultEditStyles(), rect, pParentWnd, nID);
- }
-
- // Specify address where mfc should store the address for the window process
- WNDPROC* CTer::GetSuperWndProcAddr()
- {
- static WNDPROC NEAR pfnSuper;
- return &pfnSuper;
- }
-
- // Call TER menu option
- void CTer::TerMenu(WPARAM MenuOption)
- {
- if (MenuEnable(MenuOption)) TerWindowProc(WM_COMMAND,MenuOption,0L);
- }
-
- // Call TER window process
- LRESULT CTer::TerWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
- {
- WNDPROC pfnWndProc = *GetSuperWndProcAddr();
- #ifdef STRICT
- return ::CallWindowProc(pfnWndProc, m_hWnd, nMsg, wParam, lParam);
- #else
- return ::CallWindowProc((FARPROC)pfnWndProc, m_hWnd, nMsg, wParam, lParam);
- #endif
- }
-
- // Return edit styles to be used with the window
- DWORD CTer::DefaultEditStyles()
- {
- return WS_CHILD|WS_VISIBLE|WS_BORDER|TER_WORD_WRAP|TER_VSCROLL|TER_BORDER_MARGIN|TER_SHOW_TOOLBAR; // control style
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // File io functions
- void CTer::DeleteContents()
- {
- HGLOBAL hMem;
- LPSTR pMem;
-
- ASSERT_VALID(this);
- ASSERT(m_hWnd!=NULL);
-
- // allocate an empty buffer
- hMem=::GlobalAlloc(GMEM_MOVEABLE,1);
- pMem=(LPSTR)::GlobalLock(hMem);
- pMem[0]=0xD; // line delimiter
- ::GlobalUnlock(hMem);
-
- SetHandle(hMem,1,NULL,TRUE);
-
- ASSERT_VALID(this);
- }
-
- DWORD CTer::GetBuffer()
- // Retrieve the text buffer from the control
- {
- if (m_hBuffer) ::GlobalFree(m_hBuffer);
-
- m_hBuffer=GetHandle((long far *)&m_BufLen);
- return m_BufLen;
- }
-
- // Read and write CTer object to archive, with a 4 byte length prefix.
- void CTer::Serialize(CArchive& ar)
- {
- ASSERT_VALID(this);
- ASSERT(m_hWnd != NULL);
-
- if (ar.IsStoring()) { // Save data
- DWORD nLen = GetBuffer();
- ar << nLen; // write length
- WriteArchive(ar);
- }
- else { // load data
- DWORD dwLen;
- ar >> dwLen; // read length
- ReadArchive(ar, dwLen);
- }
- ASSERT_VALID(this);
- }
-
- // Read certain amount of text from the file, assume at least nLen
- // bytes are in the file.
- void CTer::ReadArchive(CArchive& ar, DWORD nLen)
- {
- ASSERT_VALID(this);
-
- HGLOBAL hBuf=::GlobalAlloc(GMEM_MOVEABLE, nLen+1);
- char huge * pMem=(char huge *)GlobalLock(hBuf);
-
- if (pMem == NULL) {
- AfxThrowMemoryException();
- ASSERT(FALSE);
- }
-
- // read the buffer
- DWORD BlockSize=0x4000; // 16 blocks
- DWORD BytesDone=0; // bytes written so far
-
- while (BytesDone<nLen) {
- if ((BytesDone+BlockSize)>nLen) BlockSize=nLen-BytesDone;
-
- if (ar.Read(&(pMem[BytesDone]),(UINT)BlockSize)!=(UINT)BlockSize) {
- ::GlobalUnlock(hBuf);
- AfxThrowArchiveException(CArchiveException::endOfFile);
- ASSERT(FALSE);
- }
- BytesDone+=BlockSize;
- }
-
- // pass the handle to the control
- pMem[nLen]=0;
- ::GlobalUnlock(hBuf);
- SetHandle(hBuf,nLen,"",TRUE); // control now owns the handle
-
- ASSERT_VALID(this);
- }
-
- // Write just the text to an archive, no length prefix.
- void CTer::WriteArchive(CArchive& ar)
- {
- ASSERT_VALID(this);
- ASSERT(m_hBuffer!=NULL);
-
- char huge *pMem = (char huge *)::GlobalLock(m_hBuffer);
-
- ASSERT(pMem != NULL);
-
- // direct write for a huge buffer
- TRY
- {
- DWORD BlockSize=0x4000; // 16 blocks
- DWORD BytesDone=0; // bytes written so far
-
- while (BytesDone<m_BufLen) {
- if ((BytesDone+BlockSize)>m_BufLen) BlockSize=m_BufLen-BytesDone;
- ar.Write(&(pMem[BytesDone]),(UINT)BlockSize);
- BytesDone+=BlockSize;
- }
- }
- CATCH_ALL(e)
- {
- ::GlobalUnlock(m_hBuffer);
- THROW_LAST();
- ASSERT(FALSE);
- }
- END_CATCH_ALL
-
- // release our buffer
- ::GlobalUnlock(m_hBuffer);
- ::GlobalFree(m_hBuffer);
- m_hBuffer=0;
- m_BufLen=0;
-
- // mark the window as updated
- SetModify(FALSE);
-
- ASSERT_VALID(this);
- }
-
- void CTer::SerializeRaw(CArchive& ar)
- // Read/Write object as stand-alone file.
- {
- ASSERT_VALID(this);
- if (ar.IsStoring()) { // save data
- GetBuffer(); // retrieve data from control
- WriteArchive(ar);
- }
- else { // load file
- CFile *pFile = ar.GetFile();
- ASSERT(pFile->GetPosition() == 0);
- DWORD nFileSize = pFile->GetLength();
- ReadArchive(ar,nFileSize);
- }
- ASSERT_VALID(this);
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // Menu Commands
- // These functions simply invoke the given menu option
- //////////////////////////////////////////////////////////////////////////
- // Check if a menu item should be enabled
- BOOL CTer::MenuEnable(int MenuItem)
- {
- if (m_hWnd && MF_ENABLED==::TerMenuEnable(m_hWnd,MenuItem)) return TRUE;
- else return FALSE;
-
- }
-
- // Check if a menu item should be selected
- int CTer::MenuSelect(int MenuItem)
- {
- if (m_hWnd && MF_CHECKED==::TerMenuSelect(m_hWnd,MenuItem)) return 1;
- else return 0;
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- // CTer API functions
-
- // Get the handle to the control data
- HGLOBAL CTer::GetHandle(long far *BufferLen) {return GetTerBuffer(m_hWnd,BufferLen);}
-
- // Set new text to the control
- BOOL CTer::SetHandle(HGLOBAL hBuffer, long BufferLen, LPSTR title, BOOL release) {
- BOOL result;
- TerEnableRefresh(m_hWnd,FALSE); // suppress painting by SetTerBuffer function
- result = SetTerBuffer(m_hWnd,hBuffer,BufferLen, (LPBYTE)title, release);
- TerEnableRefresh(m_hWnd,TRUE); // resume painting
- return result;
- }
-
- void CTer::Cut() {TerMenu(ID_CUT);}
- void CTer::Copy() {TerMenu(ID_COPY);}
- void CTer::Paste() {TerMenu(ID_PASTE);}
- BOOL CTer::CanUndo() {return MenuEnable(ID_UNDO);}
- BOOL CTer::Undo() {TerMenu(ID_UNDO);return TRUE;}
-
- // get the beginning and ending position of a highlighted block.
- // EndPos points to the character immediately after the block
- void CTer::GetSel(long &StartPos,long &EndPos)
- {
- StrTerField field;
-
- StartPos=EndPos=0;
- ::GetTerFields(m_hWnd,&field);
-
- if (field.HilightTypeW!=HILIGHT_OFF) {
- if (field.HilightTypeW==HILIGHT_LINE) {
- field.HilightBegColW=0;
- field.HilightEndColW=field.LineLenW; // entire line highlighted
- }
- StartPos=TerRowColToAbs(m_hWnd,field.HilightBegRowW,field.HilightBegColW);
- EndPos=TerRowColToAbs(m_hWnd,field.HilightEndRowW,field.HilightEndColW);
-
- if (StartPos>EndPos) { // swap the values
- long temp=StartPos;
- StartPos=EndPos;
- EndPos=temp;
- }
- }
- }
-
- // Delete any highlighted block
- void CTer::Clear()
- {
- long StartPos,EndPos;
-
- GetSel(StartPos,EndPos);
-
- if (EndPos>0) TerMenu(ID_DEL); // send the DEL key message
- }
-
- // Check if text modified
- BOOL CTer::GetModify()
- {
- StrTerField field;
-
- ::GetTerFields(m_hWnd,&field);
-
- return field.modified;
- }
-
- // set or reset modification status
- void CTer::SetModify(BOOL bModified) {::TerSetModify(m_hWnd,bModified);}
-
- // Get total number of lines the in the document
- long CTer::GetLineCount()
- {
- StrTerField field;
-
- ::GetTerFields(m_hWnd,&field);
-
- return field.TotalLinesW;
- }
-
- // retrieve the character index of the line. Set nLine to -1 to specify
- // the current line. The nLine is zero based parameter.
- long CTer::LineIndex(long nLine)
- {
- if (nLine<0) { // get the current line
- StrTerField field;
- ::GetTerFields(m_hWnd,&field);
- nLine=field.CurLineW;
- }
-
- return ::TerRowColToAbs(m_hWnd,nLine,0);
- }
-
- // set or reset modification status
- BOOL CTer::SetReadOnly(BOOL bReadOnly) {return ::TerSetReadOnly(m_hWnd,bReadOnly);}
-
- // Retrieve the specified line.
- int CTer:: GetLine(long index, LPSTR buffer)
- {
- WORD MaxLength;
-
- MaxLength=*((LPWORD)buffer); // retrive max bytes to copy
- return GetLine(index,buffer,(int)MaxLength);
- }
-
- int CTer::GetLine(long index, LPSTR buffer, int MaxLength)
- {
- char string[301];
- int LineLen,i;
-
- *((LPWORD)buffer)=(WORD)MaxLength; // store maximum number of bytes to copy
-
- if ((LineLen=::GetTerLine(m_hWnd,index,(LPBYTE)string,NULL))<=0) return 0;
-
- if (LineLen>MaxLength) LineLen=MaxLength;
-
- for (i=0;i<LineLen;i++) buffer[2+i]=string[i]; // first word reserved for line length
-
- return LineLen;
- }
-
- // get the line index of the first line on the screen
- long CTer::GetFirstVisibleLine()
- {
- StrTerField field;
-
- ::GetTerFields(m_hWnd,&field);
-
- return field.BeginLineW;
- }
-
- // get the line number (0 based) from the character index (0 based).
- // when nIndex is -1, the number of the line that contains the first character
- // of the selection is returned. If there is no selection, the current line
- // number is returned.
- long CTer::LineFromChar(long nIndex)
- {
- long line;
- int col;
-
- if (nIndex<0) {
- StrTerField field;
- ::GetTerFields(m_hWnd,&field);
-
- if (field.HilightTypeW!=HILIGHT_OFF) return field.HilightBegRowW;
- else return field.CurLineW;
- }
-
- TerAbsToRowCol(m_hWnd,nIndex,&line,&col);
-
- return line;
- }
-
- // Get the length of the line which contains a character at an index
- // equal to nLine. if nLine is -1, the function returns total number of
- // unselected lines in the first and last highlighted line.
- int CTer::LineLength(long nLine)
- {
- if (nLine>=0) return ::GetTerLine(m_hWnd,nLine, NULL,NULL); // get the length of the specified line
-
- // test if a block highlighted
- StrTerField field;
- ::GetTerFields(m_hWnd,&field);
-
- if (field.HilightTypeW==HILIGHT_OFF) return field.LineLenW; // return the length of the current line
-
- // count the un-highlighted characters in the first and last line
- if (field.HilightTypeW==HILIGHT_LINE) return 0; // entire lines highlighted
-
- int EndLineLen=::GetTerLine(m_hWnd,field.HilightEndRowW,NULL,NULL);
-
- return field.HilightBegColW+EndLineLen-field.HilightEndColW;
-
- }
-
- // Scroll specified number of lines in the vertical or horizontal direction
- void CTer::LineScroll(long nLines, int nChars)
- {
- StrTerField field;
- int i;
- WORD wParam;
-
- // disable painting
- ::GetTerFields(m_hWnd,&field);
- field.PaintEnabledW=FALSE;
- ::SetTerFields(m_hWnd,&field);
-
- // scroll vertically
- if (nLines) {
- wParam=SB_LINEDOWN; // send line down message
- if (nLines<0) {
- wParam=SB_LINEUP;
- nLines=-nLines;
- }
- for (i=0;i<nLines;i++) TerWindowProc(WM_VSCROLL,wParam,0L);
- }
-
- if (nChars) {
- wParam=SB_LINEDOWN; // send line down message
- if (nChars<0) {
- wParam=SB_LINEUP;
- nChars=-nChars;
- }
- for (i=0;i<nChars;i++) TerWindowProc(WM_HSCROLL,wParam,0L);
- }
-
- // enable painting
- ::GetTerFields(m_hWnd,&field);
- field.PaintEnabledW=TRUE;
- ::SetTerFields(m_hWnd,&field);
- }
-
- // Replace the exiting highlighted text by the specified text. If a block
- // is not highlighted, the new text is inserted at the current cursor location.
- void CTer::ReplaceSel(char huge *NewText)
- {
- StrTerField field;
-
- // Delete the exiting text
- ::GetTerFields(m_hWnd,&field);
- if (field.HilightTypeW!=HILIGHT_OFF) {
- TerMenu(ID_DEL); // send the DEL key message
- ::SetTerCursorPos(m_hWnd,field.HilightBegRowW, field.HilightBegColW, FALSE);
- }
-
- InsertTerText(m_hWnd,(LPBYTE)NewText,TRUE);
-
- }
-
- // Highlight a block of text. if nStartChar is 0 and nEndChar is -1,
- // the entire text is highlighted. If nStartChar is -1, any current
- // highlighting is turned off.
-
- void CTer::SetSel(long nStartChar, long nEndChar, BOOL bNoScroll)
- {
- if (nStartChar==-1) { // remove any highlighting
- ::DeselectTerText(m_hWnd,TRUE);
- return;
- }
-
- if (nStartChar==0 && nEndChar==-1) { // select the entire text
- StrTerField field;
- ::GetTerFields(m_hWnd,&field);
- int len=::GetTerLine(m_hWnd,field.TotalLinesW-1,NULL,NULL); // length of the last line
- ::SelectTerText(m_hWnd,0,0,field.TotalLinesW-1,len,bNoScroll);
-
- if (!bNoScroll) { // set the cursor at the end of the block
- int LineLen=::GetTerLine(m_hWnd,field.TotalLinesW-1,NULL,NULL);
- if (field.WordWrapW && LineLen>0) LineLen--;
- ::SetTerCursorPos(m_hWnd,field.TotalLinesW-1, LineLen, TRUE);
- }
- return;
- }
-
- // select the specified line
- ::SelectTerText(m_hWnd,nStartChar,-1,nEndChar+1,-1,bNoScroll);
- if (!bNoScroll) { // set the cursor at the end of the block
- long line;
- int col;
- TerAbsToRowCol(m_hWnd,nEndChar+1,&line,&col);
- ::SetTerCursorPos(m_hWnd,line, col, TRUE);
- }
-
- }
-