home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------*/
- /* filename - tfield.cpp */
- /* */
- /* function(s) */
- /* TField member functions */
- /*------------------------------------------------------------*/
-
- /*------------------------------------------------------------*/
- /* */
- /* Turbo Vision - Version 1.0 */
- /* Turbo Vision Extensions -- Version 1.0.0 */
- /* */
- /* */
- /* Portions Copyright (c) 1991 by Borland International */
- /* All Rights Reserved. */
- /* */
- /* TV Extensions are Copyright (c) 1992 by Michael Bonner */
- /* These extensions may be freely used by any programmer */
- /* including royalty free inclusion in any commercial */
- /* application, but any commercial rights to the source */
- /* code or object files of the Extensions are reserved. */
- /* */
- /*------------------------------------------------------------*/
-
- #define Uses_TKeys
- #define Uses_TView
- #define Uses_TDrawBuffer
- #define Uses_TEvent
- #define Uses_opstream
- #define Uses_ipstream
- #define Uses_TField
- #include <tv.h>
- #include "tfield.h"
-
- #if !defined( __CTYPE_H )
- #include <ctype.h>
- #endif // __CTYPE_H
-
- #if !defined( __STRING_H )
- #include <String.h>
- #endif // __STRING_H
-
- #if !defined( __DOS_H )
- #include <Dos.h>
- #endif // __DOS_H
-
- #if !defined( __MEM_H )
- #include <Mem.h>
- #endif // __MEM_H
-
-
- const int CONTROL_Y = 25;
-
- char hotKey( const char *s )
- {
- char *p;
-
- if( (p = strchr( s, '~' )) != 0 )
- return toupper(p[1]);
- else
- return 0;
- }
-
- #define cpField "\x13\x13\x14\x15"
-
-
- const char * const near TField::name = "TField";
- const char near TField::rightArrow = '\x10';
- const char near TField::leftArrow = '\x11';
-
-
- TField::TField( const TRect& bounds, int aMaxLen ) :
- TView(bounds),
- data( new char[aMaxLen] ),
- maxLen( aMaxLen-1 ),
- curPos( 0 ),
- firstPos( 0 ),
- selStart( 0 ),
- selEnd( 0 )
- {
- state |= sfCursorVis;
- options |= ofSelectable | ofFirstClick;
- *data = EOS;
- //
- // 1/16/92 -- MBB
- // Added support for the scrollState variable in the constructor.
- // scrollState is initialized to True by default, which enables scrolling.
- // Call the function setScroll( False ) to disable scrolling.
- //
- scrollState = True;
- //
- // 1/17/92 -- MBB
- // Added support for the justification variable in the constructor.
- // justification is initialized to jLeft by default.
- //
- justification = jLeft;
-
- }
-
- TField::~TField()
- {
- delete data;
- }
-
- Boolean TField::canScroll( int delta )
- {
- //
- // 1/16/92 -- MBB
- // Added check of scrollState before allowing scrolling. If scrollState
- // is 0 then no scrolling can occur and this routine returns False
- // always. If scrollState is not 0 then this routine works like it did
- // in TInputLine.
- //
- if( scrollState) {
- //
- // scrollState is not 0, process the scroll request
- //
- if( delta < 0 )
- return Boolean( firstPos > 0 );
- else
- if( delta > 0 )
- return Boolean( strlen(data) - firstPos + 2 > size.x );
- else
- return False;
- }
- else
- //
- // scrollState is 0, return false
- //
- return False;
- }
-
- ushort TField::dataSize()
- {
- return maxLen+1;
- }
-
- void TField::draw()
- {
- //************************************************************************
- // 1/23/92 -- MBB
- // Rewrote section to provide support to enable/disable scrolling and
- // to handle right justification
- //************************************************************************
-
- const int bufferSize = 256;
-
- int selectFirst = 0, // formerly l,
- // used to calc position of the first
- // selected character in the TDrawBuffer
- selectLast = 0, // formerly r,
- // used to calc position of the last
- // selected character in the TDrawBuffer
- dataLen = strlen(data), // holds the length of the data string
- cursorPosition = 0, // holds the new cursor postion
- displaySize = size.x, // holds the # characters of the current
- // TRect which will be used to display data
- dataOffset = firstPos, // holds the offset into the data string
- bufOffset = 0, // holds the offset into the buf buffer
- // used w/ jRight to add leading spaces
- bOffset = 0; // holds the offset into the b buffer
- // used w/ scrollState to leave room for
- // leftArrow
-
- TDrawBuffer b;
-
- //
- // decide if we use the focused or not-focused color
- //
- uchar color = (state & sfFocused) ? getColor( 2 ) : getColor( 1 );
-
- //
- // clear the display buffer
- //
- b.moveChar( 0, ' ', color, size.x );
-
- char buf[bufferSize]; // create a temporary character buffer
- memset(buf, ' ', size.x); // clear the portion of the buffer we'll use
- // ^^^^^^^^^^^^^^^^^^^^^^
- // This could be a problem if size.x > bufferSize, but since this routine
- // is called frequently, I want to keep the overhead down as much as
- // possible, so I won't perform error checking. Be aware of this if you
- // change the bufferSize variable!
- //
-
- //************************************************************************
- // 1/23/92 -- MBB
- // rewrote this section to compute all offsets and positions based on the
- // current state of scrollState and justification.
- //************************************************************************
- if (scrollState) {
- //
- // Compute offsets and positions to allow for scrolling
- // (ie. leave room for arrows)
- //
- bOffset = 1; // leave room for the left arrow at the
- // start of the line
- displaySize -= 2; // adjust display size to leave room for
- // two arrows on the line
-
- //
- // Put the arrows in the buffer if they are needed
- //
- if( (state & sfSelected) != 0 ) {
- if( ((state & sfSelected) != 0) && (canScroll(1)) )
- b.moveChar( size.x-1, rightArrow, getColor(4), 1 );
- if( ((state & sfSelected) != 0) && (canScroll(-1)) )
- b.moveChar( 0, leftArrow, getColor(4), 1 );
- };
- }
- else {
- //
- // Compute the offsets and positions that ignore scrolling
- //
- //dataOffset = 0;
- };
-
- if ( (state & sfSelected) != 0 )
- {
- //
- // calculate offset for right justification
- //
- if ( (justification == jRight) && (dataLen <= displaySize) ) {
- bufOffset = displaySize - dataLen;
- //
- // Add an additional character to the end of the field
- // unless the data just fits the field
- //
- if (maxLen < displaySize)
- bufOffset--;
- };
- //
- // Calculate the selected positions and cursor position
- //
- selectFirst = selStart - firstPos;
- selectLast = selEnd - firstPos;
- selectFirst = max( 0, selectFirst ) + bufOffset;
- selectLast = min( displaySize, selectLast ) + bufOffset;
- cursorPosition = curPos - firstPos + bOffset + bufOffset;
- };
-
-
- //************************************************************************
- // 1/23/92 -- MBB
- // rewrote this section to update the display based on the computed
- // offsets and positions (cleaned up multiple if's & case structures
- // so code would be easier to maintain.)
- //************************************************************************
-
- //
- // Copy from the data string to the buf string
- //
- strncpy( buf+bufOffset, data+dataOffset, min(displaySize, dataLen) );
- //
- // set the last character in buf to end of string to keep display clean
- //
- if (bufOffset > 0)
- buf[ displaySize ] = EOS;
- else
- buf[ min(displaySize, dataLen) ] = EOS;
- //
- // move characters from the buf into the TDrawBuffer b
- //
- b.moveStr( bOffset, buf, color );
- //
- // change the color of any selected text
- //
- if (selectFirst < selectLast)
- b.moveChar( selectFirst + bOffset, 0, getColor(3),
- min(selectLast - selectFirst, dataLen) );
- //
- // write the buffer to the form
- //
- writeLine( 0, 0, size.x, size.y, b );
- //
- // reposition the cursor
- //
- setCursor( cursorPosition, 0);
-
- }
-
- void TField::getData( void *rec )
- {
- memcpy( rec, data, dataSize() );
- }
-
- TPalette& TField::getPalette() const
- {
- static TPalette palette( cpField, sizeof( cpField )-1 );
- return palette;
- }
-
- int TField::mouseDelta( TEvent& event )
- {
- TPoint mouse = makeLocal( event.mouse.where );
-
- if( mouse.x <= 0 )
- return -1;
- else
- if( mouse.x >= size.x - 1 )
- return 1;
- else
- return 0;
- }
-
- int TField::mousePos( TEvent& event )
- {
-
- TPoint mouse = makeLocal( event.mouse.where );
- int pos;
-
- //************************************************************************
- // 1/24/92 -- MBB
- // Compute offsets to handle the scrollState and justification stuff
- //************************************************************************
- int leadArrow = (scrollState ? 1 : 0),// offset for the beginning arrow
- displaySize = (scrollState ? size.x - 2 : size.x),
- // x size used for display
- dataLen = strlen(data), // length of the data item
- jOffset = 0; // justification offset
-
- //
- // Calculate offset when justification is active
- //
- if ( (justification == jRight) && (dataLen <= displaySize) ) {
- jOffset = displaySize - dataLen;
- if (maxLen < displaySize)
- jOffset--;
- };
-
- mouse.x = max( mouse.x, leadArrow );
- pos = mouse.x + firstPos - jOffset - leadArrow;
-
- pos = max( pos, 0 );
- pos = min( pos, strlen(data) + jOffset );
- return pos;
- }
-
- void TField::deleteSelect()
- {
- if( selStart < selEnd )
- {
- strcpy( data+selStart, data+selEnd );
- curPos = selStart;
- }
- }
-
- void TField::handleEvent( TEvent& event )
- {
- TView::handleEvent(event);
-
- int delta, anchor, i;
- if( (state & sfSelected) != 0 )
- switch( event.what )
- {
- case evMouseDown:
- if( canScroll(delta = mouseDelta(event)) )
- do {
- if( canScroll(delta) )
- {
- firstPos += delta;
- drawView();
- }
- } while( mouseEvent( event, evMouseAuto ) );
- else if (event.mouse.doubleClick)
- selectAll(True);
- else
- {
- anchor = mousePos(event);
- do {
- if( event.what == evMouseAuto &&
- canScroll( delta = mouseDelta(event) )
- )
- firstPos += delta;
- curPos = mousePos(event);
- if( curPos < anchor )
- {
- selStart = curPos;
- selEnd = anchor;
- }
- else
- {
- selStart = anchor;
- selEnd = curPos;
- }
- drawView();
- } while (mouseEvent(event, evMouseMove | evMouseAuto));
- }
- clearEvent(event);
- break;
- case evKeyDown:
- switch( ctrlToArrow(event.keyDown.keyCode) )
- {
- case kbLeft:
- if( curPos > 0 )
- curPos--;
- break;
- case kbRight:
- if( curPos < strlen(data) )
- curPos++;
- break;
- case kbHome:
- curPos = 0;
- break;
- case kbEnd:
- curPos = strlen(data);
- break;
- case kbBack:
- if( curPos > 0 )
- {
- strcpy( data+curPos-1, data+curPos );
- curPos--;
- if( firstPos > 0 )
- firstPos--;
- }
- break;
- case kbDel:
- if( selStart == selEnd )
- if( curPos < strlen(data) )
- {
- selStart = curPos;
- selEnd = curPos + 1;
- }
- deleteSelect();
- break;
- case kbIns:
- setState(sfCursorIns, Boolean(!(state & sfCursorIns)));
- break;
- default:
- if( event.keyDown.charScan.charCode >= ' ' )
- {
- //
- // 1/23/92 -- MBB
- // Added fix for overlay mode suggested by
- // Martin Keye (CIS 100033,3020) to prevent
- // garbage characters at the last position
- // when in overstrike mode
- // Line read:
- // if ( (state & sfCursorIns ) != 0 )
- //
- if ( ((state & sfCursorIns ) != 0) &&
- (curPos < strlen(data)) )
- strcpy( data + curPos, data + curPos + 1 );
- else
- deleteSelect();
- if( strlen(data) < maxLen )
- {
- if( firstPos > curPos )
- firstPos = curPos;
- memmove( data + curPos + 1, data + curPos,
- strlen(data+curPos)+1 );
- data[curPos++] =
- event.keyDown.charScan.charCode;
- }
- }
- else if( event.keyDown.charScan.charCode == CONTROL_Y)
- {
- *data = EOS;
- curPos = 0;
- }
- else
- return;
- }
- selStart = 0;
- selEnd = 0;
- if( firstPos > curPos )
- firstPos = curPos;
- //
- // 1/23/92 -- MBB
- // Modified to take scrollState into account
- //
- i = curPos - size.x + 1;
- if (scrollState)
- i += 2;
- if( firstPos < i )
- firstPos = i;
- drawView();
- clearEvent( event );
- break;
- }
- }
-
- void TField::selectAll( Boolean enable )
- {
- selStart = 0;
- if( enable )
- curPos = selEnd = strlen(data);
- else
- curPos = selEnd = 0;
- //************************************************************************
- // 1/24/92 -- MBB
- // Modified to adjust for scrollState and justification
- //************************************************************************
- if (scrollState)
- firstPos = max( 0, curPos-size.x+3 );
- else
- firstPos = max( 0, curPos-size.x+1 );
- drawView();
- }
-
- void TField::setData( void *rec )
- {
- memcpy( data, rec, dataSize()-1 );
- data[dataSize()-1] = EOS;
- selectAll( True );
- }
-
- void TField::setScroll( Boolean enable )
- {
- if( enable )
- scrollState = True;
- else
- scrollState = False;
- //
- // Redisplay the field
- //
- drawView();
- }
-
- void TField::setJustification( int jValue )
- {
- if ( jValue == jRight )
- justification = jRight;
- else
- justification = jLeft;
- //
- // Redisplay the field
- //
- drawView();
- }
-
- void TField::setState( ushort aState, Boolean enable )
- {
- TView::setState( aState, enable );
- if( aState == sfSelected ||
- ( aState == sfActive && (state & sfSelected) != 0 )
- )
- selectAll( enable );
- }
-
- void TField::write( opstream& os )
- {
- TView::write( os );
- os << maxLen << curPos << firstPos
- << selStart << selEnd << scrollState << justification;
- os.writeString( data);
- }
-
- void *TField::read( ipstream& is )
- {
- TView::read( is );
- is >> maxLen >> curPos >> firstPos
- >> selStart >> selEnd >> scrollState >> justification;
- data = new char[maxLen + 1];
- is.readString(data, maxLen);
- state |= sfCursorVis;
- options |= ofSelectable | ofFirstClick;
- return this;
- }
-
- TStreamable *TField::build()
- {
- return new TField( streamableInit );
- }
-
- TField::TField( StreamableInit ) : TView( streamableInit )
- {
- }
-
-
-